我应该最小化泊坞窗层的数量吗?

时间:2017-11-02 15:34:35

标签: docker optimization dockerfile layer

documentation没有详细说明这个话题。它说:

  

最小化图层数

     

在Docker 17.05之前,甚至更多,之前   Docker 1.10,最大限度地减少你的层数   图片。以下改进减轻了这种需求:

     

在Docker 1.10及更高版本中,仅创建RUN,COPY和ADD指令   层。其他指令创建临时中间图像,和   不再直接增加构建的大小。

     

Docker 17.05及更高版本增加了对多阶段构建的支持   允许您仅将所需的工件复制到最终图像中。   这允许您在工具中包含工具和调试信息   中间构建阶段而不增加最终的大小   图像。

看起来最新的Docker版本无法解决处理多个层的问题。他们宁愿努力减少最终图像中的数量。最重要的是,文档并没有告诉为什么很多层都不好。

我知道42层的AUFS limit。对于广泛使用的图像,保持较小的层数是有意义的,因为它有助于构建在其上的其他图像符合限制。但是,还有其他存储驱动程序和图像用于其他目的。

将图像保持在一个明显的原因也很好 - 它们会占用磁盘空间和网络带宽。但是,我不认为chaining RUN statements并因此将多层压缩为一层有助于一般。如果不同的RUN更新文件系统的不同部分,则一层和多层的大小应该大致相同。

另一方面,许多层允许更快地使用缓存和重建图像。它们也是并行的。

我在一个拥有私有Docker注册表的小团队中工作。我们永远不会满足42层限制,主要关注性能和开发速度。

如果是这样,我应该最小化泊坞窗层的数量吗?

3 个答案:

答案 0 :(得分:20)

  

我在一个拥有私有Docker注册表的小团队中工作。我们永远不会满足42层限制,主要关注性能和开发速度。

如果是这样,我应该最小化泊坞窗层的数量吗?

在你的情况下,没有。
需要最小化的是构建时间,这意味着:

  • 确保最常用的步骤,最长的步骤,然后缓存,允许你在快速重建时间的同时摆弄Dockerfile的最后几行(最具体的命令)。
  • 确保最长的RUN命令首先出现在自己的层中(再次被缓存),而不是与其他RUN命令链接:如果其中一个失败,则必须重新执行long命令。如果该长命令在其自己的(Dockerfile行)/层中被隔离,则它将被缓存。

话虽如此,the documentation you mention来自docker/docker.github.io,正好是PR 4992PR 4854,来自docker build LABEL section。 所以这一部分是在关于LABEL的类似评论之后发生的,只是强调了创建图层的命令 同样,在您的情况下,这不重要。

答案 1 :(得分:16)

我只想看看2个图像的区别是什么,一个是用多个RUN构建的,另一个是用一个RUN连接命令构建的。

在第一种情况下,图像正在进行简单的操作(创建和删除文件)。

"单身"的内容图层图片:

FROM busybox

RUN echo This is the 1 > 1 \
    && rm -f 1 \
    && echo This is the 2 > 2 \
    && rm -f 2 \
# ... for about 70 commands

多层图片的内容:

FROM busybox

RUN echo This is the 1 > 1
RUN rm -f 1
RUN echo This is the 2 > 2
RUN rm -f 2
# ... for about 70 layers

构建时间非常不同(倍数:0m34,973s,单数:0m0,568s)。容器启动时间也不同但不太明显(多个:0m0,435s,单数:0m0,378s)。我在图像上运行的时间不同,但时间并没有那么大的改变。

关于空间,我已经考虑了多层情况下最坏情况的目的,正如预期的那样,多层图像比单层更大。

在另一个测试中,我连接了仅向图像添加内容的图层。构建时间与前一种情况相比没有变化,但运行时情况显示略有不同:多层图像的启动速度比单层图像快。关于空间,相同的结果。

我不认为这证明了什么,但我很乐意这样做:P

答案 2 :(得分:7)

减少层数本身就不是一个目标。相反,您需要关注的是缩短构建时间并减少图像尺寸。

通过保留Dockerfile顶部或基本映像中很少更改的公共图层,可以减少构建时间。这允许在以后的构建中缓存和重用该层。这不是关于减少层数,而是关于更好地排序图层。

缩小映像大小有助于减少注册表服务器上的磁盘使用量,这会在为CI系统上的每个构建存储映像时看到磁盘大量命中。它还减少了传输图像的网络时间。如果您有一个下载大型临时文件的图层并将其删除到另一个图层中,则会导致该文件保留在第一层,通过网络发送并存储在磁盘上,即使它在内部不可见你的容器。更改文件的权限还会导致文件被复制到具有新权限的当前层,从而使该文件的磁盘空间和网络带宽加倍。

在上述场景中减少图像大小的标准解决方案是链接RUN命令,以便临时文件永远不会存储到图像层。这具有减少图像层数的副作用。

还有最后一个问题,即过度缓存。这在Debian图像中的apt-get updateapt-get install ...命令中很常见。如果不将这些命令链接在一起,则apt-get install命令的更新将重用前一层apt-get update命令中可能过时的缓存,并且在几个月后无法找到所需的包时将失败。因此,您应该链接这些命令,即使它会增加构建时间,因为另一个选项是将来会出现构建失败。

因此,减少你想要的层的副作用更多,不一定是为了减少层数而减少层数。