yum安装对Docker镜像层大小的影响

5

尽管我没有IT背景,但我已经使用Docker有一段时间了。

现在,我正在努力理解如何通过优化我的Dockerfile来最小化docker镜像的大小。在这方面,我遇到了一个我不理解的最小可重现的案例。如果有人能分享他的想法或提供解释,我将非常高兴。

我从官方centos:7镜像(7e6257c9f8d8; 203MB)开始,然后准备了以下Dockerfile:

FROM centos:7
RUN yum -y install nano && yum -y clean all && rm -fr /var/cache
RUN yum -y install which && yum -y clean all && rm -fr /var/cache
RUN yum -y install which && yum -y clean all && rm -fr /var/cache

这个想法是安装任何轻量级软件包,并评估其对镜像大小的影响。为此,我首先安装nano,然后在不同的标签中安装which。我额外尝试安装which(这表明没有什么可以做的)。此外,我添加了yum clean all语句以清除yum缓存,并且为了保险起见(尽管我刚刚检查过实验结果,如果我删除此命令,实验结果不会改变),我删除/var/cache目录(该目录在基本映像中为空)。
结果如下:
IMAGE               CREATED             CREATED BY                                      SIZE  
6a14537d3460        7 seconds ago       /bin/sh -c yum -y install which && yum -y cl…   23.9MB
7d924cbdf819        22 seconds ago      /bin/sh -c yum -y install which && yum -y cl…   24.2MB
2b5b04d37a64        42 seconds ago      /bin/sh -c yum -y install nano && yum -y cle…   24.6MB
which 的安装大小为75k,nano 的安装大小为1.6M。我没有发现任何额外的已安装依赖项。

问题是:为什么即使没有实际安装任何软件包,每个安装命令都会将最终映像增加约24MB的层?

提前感谢社区:)

1个回答

3
每个RUN指令都会创建一个新的Docker层。
Docker本身并不足够聪明,无法检测到指令实际上没有做任何事情。
它会忠实地将新的Docker层存储在生成的镜像中。
这就是为什么你需要尽可能地减少Docker指令的数量。
在您的情况下,您可以只使用一个RUN指令:
RUN yum -y install nano which && yum -y clean all && rm -fr /var/cache 

UPDATE

Let's make an experiment:

FROM centos
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which
RUN yum -y install which

10条RUN指令,其中9条是“什么也不做”的。

让我们构建并查找中间图像。

$ docker build .
...
$ docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              fbd86aedc782        5 seconds ago       263MB
<none>              <none>              ca70a4bbe722        7 seconds ago       261MB
<none>              <none>              bd11e0ab02fb        9 seconds ago       259MB
<none>              <none>              68c20ddfcaad        11 seconds ago      257MB
<none>              <none>              314a6501ad23        13 seconds ago      255MB
<none>              <none>              42a62294a5e7        16 seconds ago      253MB
<none>              <none>              16fad39b9c27        18 seconds ago      251MB
<none>              <none>              6769fe69c9e1        19 seconds ago      249MB
<none>              <none>              49cef483e732        21 seconds ago      248MB
<none>              <none>              c4c92c39f2a4        23 seconds ago      246MB
centos              latest              0d120b6ccaa8        3 weeks ago         215MB

我发现每个 "什么也不做" 的 docker 镜像层大约增加了 ~2Mb 的大小。(关于 OP 问题中的 ~24Mb 我不清楚)

更新2

根据 emix 的建议:使用 dive 工具,我立即发现在每个层中都有更改的文件位于 /var/rpm/var/log 目录下。


谢谢Alex。当然,将这三个指令作为三个不同步骤运行是没有意义的。这只是一个有用的例子,用来研究docker的行为。你的意思是说,这~24MB是添加一个(几乎)空图层的内在额外大小吗? - J. Berzosa
@J.Berzosa 我的实验表明,使用yum install每层速度为2Mbs,而touch /some_file && rm /some_file的速度则较慢,但这是由于docker存储层的本质原因。 - Alex Yu
刚刚重复了你的实验,复制并粘贴了你的Dockerfile。在我的情况下,第一层实际安装需要30.6MB,而其他层只需要10.3MB(在你的情况下只有2MB...)。我正在Centos OS中运行docker。 - J. Berzosa
刚刚验证了一下,执行“touch kk”命令不会占用任何空间。因此,我们观察到的不能单纯地归因于 Docker 镜像层本身的固有大小。 - J. Berzosa
1
只需使用 dive 检查您的镜像层。 - Mike Doe
@emix 谢谢!我立即在 /var/lib/rpm 找到了被更改的文件。 - Alex Yu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接