1
jdhao 2021-02-28 13:08:15 +08:00 via Android 2
当然是 dockerfile 的方式,便于知道里面到底装了啥,做了什么操作,docker commit 到最后变成黑箱,你都不知道里面有啥。
去如果只追求能跑就行,用哪种方式都随便 |
2
mimzy 2021-02-28 13:09:20 +08:00 1
Docker 的机制是可以复用之前的层,加快 build 速度减少体积占用,每次都 docker commit 相当于都没法复用了,所以 1 正确。
|
3
boris93 2021-02-28 13:42:35 +08:00 via iPhone
1 正确
你要想让镜像之间有父子关系的话,后面构建就 FROM 上一版本镜像,虽然不知道有什么意义 |
4
muzuiget 2021-02-28 13:44:32 +08:00
我一向用 1,docker 本来就是可以自动复用之前的层的,但是把改动都写到 dockerfile 了清晰好多。
|
5
mimzy 2021-02-28 13:52:59 +08:00
@mimzy #2 我这里之前理解得不对,commit 也可以复用,问题在于这个复用会在上一层原封不动的基础上修改,镜像会越来越臃肿…
|
6
dangyuluo 2021-02-28 14:38:04 +08:00
第一步:正确拼写 docker
|
7
dangyuluo 2021-02-28 14:39:17 +08:00 1
在正确掌握拼写的基础上,我们公司使用的是第一种策略
|
8
jim9606 2021-02-28 15:05:43 +08:00
2 只适合增量的情况(同版本增加插件和可选依赖),如果是替换(更新依赖、更新程序本体)应该用 1,因为多层 commit 会保留中间层中被删除的部分,空占体积。
虽然直接发布 dockerfile 才是最高效的方式,不过考虑到网络情况很多人不喜欢用。 2 还应该善用多阶段构建来节省最终镜像体积,不要把工具链和中间产物留在镜像里。 |
9
fiveelementgid 2021-02-28 15:44:30 +08:00 via Android
Docker 写 Dockerfile 叠千层饼比较好(云 docker 玩家路过
|
10
xuanbg 2021-02-28 15:52:05 +08:00
1
|
11
wellhome OP 感谢诸位老哥的回答。个人感觉 docker 本身的 commit 的使用场景不多。快速打个系统的补丁。如果是程序发布了话,还是需要每次都是一个干净的 image 。
|
13
konakona 2021-02-28 17:05:33 +08:00
肯定不會是 2,你會後悔的。
正確答案是 1 。 |
14
JamesMackerel 2021-02-28 17:14:11 +08:00 2
@wellhome
我觉得楼主的疑问在于,既然我每次发布的时候都不从上一个版本的 docker image commit,那这个命令到底有什么用? 其实在看这个命令有什么用的时候,不应该只从自己面前遇到的这个场景来看。docker commit 的这个设计的目的是增加存储层的复用程度。如果是 docker image 的终端用户(意思是你作出的镜像不会再被别人 FROM 或者 commit 新的东西)可能并没有什么感受,但想象以下的场景: A 制作了一个最简单最干净的 Ubuntu 镜像 - B 基于上述镜像做了一个 Python runtime 镜像,只要基于该镜像起一个容器就能直接跑 python 脚本 - - C 基于 B 制作了一个 uwsgi 镜像,只要把 wsgi 脚本放进去就能起一个服务 - - D 基于 B 制作了一个安装了一些数据分析软件包的镜像,使用者只要起一个容器就能直接在 Ipython 中进行简单的数据分析操作 这样其实 BCD 都复用了 A,CD 复用了 B 。试想如果没有这个 commit 的功能,这五个镜像就是五份完全独立的文件,由于 BCD 的改动并不多,其实相当于用 4*A 的大小,但是实际上只做了一点(真正)微小的工作。而基于 commit 机制的这些镜像在都保存在 docker registry 时,应该只占用比 A 的大小稍大一点的空间。 这种机制对于社区来说是非常有益的,因为它提供给了镜像制作者一种非常廉价的复用他人已有工作的方式,同时节省了许多存储空间。 |
15
Lemeng 2021-02-28 17:16:53 +08:00
我说呢,docker
|
16
fannas 2021-02-28 17:25:38 +08:00 via iPhone 1
个人经验:
正确姿势是第一个,第二层是运行时,第三层 dependency,第四层 config,第五层代码。 jvm 例子:Base+jdk+所有 dependency+logconfig+class code python 例子:Base + python+dependency (不要远程安装)+ config + code |
17
fannas 2021-02-28 17:26:21 +08:00 via iPhone
哦,java 最简单的方式是 jib
|
18
wellhome OP @JamesMackerel 受教了。👍
|
20
fannas 2021-02-28 21:11:53 +08:00 via iPhone
@wellhome 按照修改频率升序排列,只是个人经验哈。因为这样可以更高效的运用已有的层,在建立 image 的时候更好地利用缓存,publish 的时候节省更多带宽与空间。
|
21
wellhome OP @fannas 1 2 3 层 每次在发布 code 的时候 ,都用 DockerFile 从头打包?
|
22
jinliming2 2021-02-28 23:30:37 +08:00
@fannas 配置 config 不应该设置为运行时从环境变量里读吗?或者设置为 mount point 在运行时指定导入进去?
|
23
chenqh 2021-02-28 23:35:22 +08:00
有一个问题,docker 怎么用起来比较好,单机 docker registry 有点浪费呀
|
24
jinliming2 2021-02-28 23:40:55 +08:00
@wellhome Dockerfile 只有第一次会从头打包,后续发布更新都不会从头打包,只会从变化的位置开始打包,之前没有变化的 Dockerfile 语句都会复用。比如:
FROM xxxxxx # 这一句每次都一样,直接复用 RUN apt-get update && apt install -y xxx # 这一句也是每次都一样,直接复用 COPY . . # 这一句开始,因为拷入的代码文件变了,所以从这一行开始后面的全部重新构建 RUN build ... # 从上一句开始从新构建 所以一般来说,安装依赖之类的语句尽可能提前,这样后续打包的时候就不会重新构建了。 实际上你可以简单理解成你的 Dockerfile 里每一条语句都是一个 commit (不正确,部分语句是会合并的),相互之间就是父子关系。具体表现在你 docker pull / push 的时候显示的那个进度条的个数。你每次构建的时候,如果这条语句前面的环境都是一样的话,并且当前这一层没有任何变化的话,那么这一条语句就不会重新执行,而是直接复用之前的构建结果。这样一来你会发现,在重新 docker push 的时候,会提示你部分层已经在服务器上存在了,只会 push 变动的部分。 |
25
wellhome OP @jinliming2 "RUN apt-get update && apt install -y xxx # 这一句也是每次都一样,直接复用", 复用的前提是你本地已经有 cache, 我们的的 ci/cd 的 agent 是随机分配的。如果进行发布的 agent 上以前没有打过包,也就是说没有 cache, 那么应该还是从头开始一层一层打, 没有复用。
|
26
SmiteChow 2021-03-01 10:23:28 +08:00
docker commit 用于复用他人的镜像场景。当你不知道或不关心镜像 Dockerfile 怎么写的,但你又想复用镜像的时候,commit 能快速生成包含你修改的新镜像。
|
27
dier 2021-03-01 13:45:59 +08:00
基于你们项目运行的环境打一个基础镜像,例如(系统--软件--环境变量),然后每次发新代码时,在 Dockerfile 中 FROM 这个基础镜像来构建一个最新代码的镜像,发布的时候就发布最新的镜像。有基础镜像就可以提交镜像构建的速度,不需要次都去安装各种软件,特别是每次的 agent 不在同一台机器上没法利用之前的 cache 的环境。
|
28
ku360517703 2021-03-01 17:40:30 +08:00
方案 1 和打包镜像然后-v 挂载 jar 包进去运行,应该选哪种呢?
|
29
fannas 2021-03-02 03:05:30 +08:00 via iPhone
@wellhome 取决于实际情况。对于基础开发,例如 jvm python 我通常情况下使用 jre base 和 python base,在这个上加 dependency config 和 code 。没必要自己建立。如果有特殊需要就需要从头搞了。只是个人情况哈。
|
30
fannas 2021-03-02 03:12:11 +08:00 via iPhone
@jinliming2 config 可能用的不准确。在 jvm 软件开发的时候,resource 里面的文件通常是静态的,不进行修改的。如果这是一个离线文档 parser 或者是个生产上的预测模型,可能存在该文件夹大小几十兆甚至更大。
这种情况下先将其放入 image,最大化的减小构建 image 的大小,有利于快速分发部署。 |