工作中最近用到 docker,今天看了一天网上的教程看网上的教程 https://www.runoob.com/docker/docker-dockerfile.html
注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
以上执行会创建 3 层镜像。可简化为以下格式:
FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz
这里我试了这两种写法,docker 镜像的大小一样,这里制作 docker 镜像这两种写法有没有区别? centos:v3 是 3 个 run 生成的,v4 是第二种写法生成的。
[root Dockerfile]#docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
centos v4 ede9b36dd800 8 seconds ago 260MB
centos v3 6df19efb1980 3 minutes ago 260MB
nginx v3 3ca44131eb70 6 hours ago 133MB
1
muzuiget 2021-08-07 23:41:47 +08:00
你这个示例数据量不足到可以看出明显区别。
加多一个 RUN rm redis.tar.gz 就好了,后一种方法会少一个 redis.tar.gz 的大小。 |
2
singerll 2021-08-07 23:42:46 +08:00 via Android
你的操作太少了,而且几乎都是下载文件的操作
|
3
hefish 2021-08-07 23:48:28 +08:00
我觉着就上面的操作,没啥区别。不在乎那点。
|
4
jj256 2021-08-08 00:11:20 +08:00 via iPhone
dockerfile 里每次 run 生成的层只包含不同的部分,这点可以看下 docker 的 overlay 文件系统。所以我觉得只要执行的指令是一样的,分几层对镜像大小影响不大。
|
5
statumer 2021-08-08 01:08:36 +08:00 1
不要过早搞优化,精简镜像有很多方式,你真正在工作中遇见镜像产生瓶颈的情况再处理
在你这种情况,你观察一下命令行的输出会发现,实际上 docker 会自动移除一些中间层 |
6
Bromine0x23 2021-08-08 01:20:44 +08:00
如果命令执行结果只是单纯的文件新增,合不合并区别不大。但是如果存在文件修改和文件删除的话,合并后大小就能减少。
原因就是分层存储导致文件修改和文件删除的变化并不会影响到上层,从而整个镜像存储了无用的数据。 |
7
joetse 2021-08-08 03:40:10 +08:00
开发中分几层都无所谓, 能复用降低 build 的时间就行, 最终精简几乎都是用 from alpine copy --from=builder xx:yy
|
8
wd 2021-08-08 07:25:21 +08:00 via iPhone
膨胀主要是你在下一层无法清理上一层的文件,如果你没有这个需要,那应该无论顺序如何都一样。
|
9
ampedee 2021-08-08 08:41:17 +08:00 via Android
由于联合文件系统的存在,分再多层对镜像的体积影响也不大,合并指令的目的是为了清理无用的中间过程文件。
推荐花个几分钟看下这篇介绍容器镜像原理的文章: https://www.waynerv.com/posts/learn-image-and-container-with-oci-spec/ |
10
ragnaroks 2021-08-08 09:44:49 +08:00
你这本来就没区别,都是增加文件的操作,你起码最后要有个移除文件的操作
|
11
ch2 2021-08-08 09:45:47 +08:00
镜像大小无所谓的,大不了删了就是
|
12
jim9606 2021-08-08 15:09:29 +08:00
你这个例子只有新增文件,大小区别基本没有,只有包含删除文件的操作才能体现区别。
如果你这里的增加到下载、解压、编译、安装步骤,那么后面把源码和中间产物删掉才能体现区别。 我个人并不喜欢将这几个步骤合并,因为 build 镜像时没法保留中间结果,导致每次出错重试都得重下源码。我倾向于用多阶段构建( Dockerfile 包含多个 FROM ) |