我应该尽量减少 docker 层的数量吗?
Should I minimize the number of docker layers?
documentation 没有详细说明这个主题。它说:
Minimize the number of layers
Prior to Docker 17.05, and even more, prior to
Docker 1.10, it was important to minimize the number of layers in your
image. The following improvements have mitigated this need:
In Docker 1.10 and higher, only RUN, COPY, and ADD instructions create
layers. Other instructions create temporary intermediate images, and
no longer directly increase the size of the build.
Docker 17.05 and higher add support for multi-stage builds, which
allow you to copy only the artifacts you need into the final image.
This allows you to include tools and debug information in your
intermediate build stages without increasing the size of the final
image.
看来最新的Docker版本没有解决处理多层的问题。他们宁愿努力减少最终图像中的数量。最重要的是,文档没有告诉 为什么 许多层都不好。
我知道 AUFS limit 有 42 层。对于广泛使用的图像,保持较小的层数是有意义的,因为它有助于在它们之上构建的其他图像符合限制。但是,还有其他存储驱动程序和图像用于其他目的。
将图像保持较小也很好,原因很明显 - 它们会占用磁盘 space 和网络带宽。但是,我认为 并因此将许多层压缩成一个通常没有帮助。如果不同的 RUN 更新文件系统的不同部分,一层和许多层的大小应该大致相同。
另一方面,许多层允许使用缓存并更快地重建图像。也是平行拉的。
我在一个拥有私有 Docker 注册表的小团队中工作。我们永远不会满足 42 层的限制,主要关心性能和开发速度。
如果是这样,我应该尽量减少 docker 层的数量吗?
我只是想看看 2 个图像有什么区别,一个是用多个 运行 构建的,另一个是用一个 运行 连接命令构建的。
在第一种情况下,图像正在执行一些琐碎的操作(创建和删除文件)。
"single"层图像的内容:
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)。我有 运行 个不同时间的图像,但时间变化不大。
关于 space,我专门针对多层情况下的最坏情况进行了研究,正如预期的那样,多层图像比单层图像大。
在另一项测试中,我连接了仅向图像添加内容的图层。构建时间与之前的情况相比没有变化,但 运行 时间的情况显示出一些不同:多层图像比单层图像启动更快。关于 space,相同的结果。
我不认为这能证明什么,但我在做的过程中很开心:P
I work in a small team with a private Docker registry. We won't ever meet the 42 layers restriction and care mostly about performance and development speed.
如果是这样,我应该尽量减少 docker 层的数量吗?
在你的情况下,没有。
需要最小化的是构建时间,也就是说:
- 确保首先执行最通用和最长的步骤,然后将其缓存,让您可以 fiddle 使用 Dockerfile 的最后几行(最具体的命令),同时有快速的重建时间.
- 确保最长的 运行 命令排在第一位并在它们自己的层中(再次被缓存),而不是与其他 运行 命令链接:如果其中一个失败,长命令将不得不重新执行。如果那个长命令在它自己的(Dockerfile 行)/层中被隔离,它将被缓存。
也就是说,the documentation you mention comes from docker/docker.github.io
, precisely PR 4992 and PR 4854, after a docker build LABEL
section。
所以本节是在关于 LABEL
的类似评论之后出现的,并且只强调创建图层的命令。
同样,在您的情况下,这并不重要。
减少层数本身并不是一个目标。相反,您需要关注的是减少构建时间并减小图像大小。
通过将很少更改的公共层保留在 Dockerfile 的顶部或基础映像中,可以缩短构建时间。这允许在以后的构建中缓存和重用该层。这与减少层数无关,更多的是对层进行排序。
减小图像大小有助于减少注册表服务器上的磁盘使用,当在 CI 系统上为每个构建存储图像时,注册表服务器会看到对磁盘的大量访问。它还减少了传输图像的网络时间。当您有一个下载大型临时文件的层并在另一层删除它时,结果是该文件留在第一层,它通过网络发送并存储在磁盘上,即使它在内部不可见你的容器。更改文件的权限也会导致文件被复制到具有新权限的当前层,使该文件的磁盘 space 和网络带宽加倍。
在上述场景中减小图像大小的标准解决方案是链接 RUN
命令,这样临时文件永远不会存储到图像层。这具有减少图像层数的副作用。
最后一个问题是缓存过多。这在 Debian 映像中的 apt-get update
和 apt-get install ...
命令中很常见。如果您不将这些命令链接在一起,对 apt-get install
命令的更新将重新使用来自前一层 apt-get update
命令的可能过时的缓存,并且在几个月后找不到所需的包时将失败。因此,即使会增加构建时间,您也应该链接这些命令,因为另一个选项是将来构建失败。
所以,更多的是你要的减层的副作用,而不一定是为了减层而减层
documentation 没有详细说明这个主题。它说:
Minimize the number of layers
Prior to Docker 17.05, and even more, prior to Docker 1.10, it was important to minimize the number of layers in your image. The following improvements have mitigated this need:
In Docker 1.10 and higher, only RUN, COPY, and ADD instructions create layers. Other instructions create temporary intermediate images, and no longer directly increase the size of the build.
Docker 17.05 and higher add support for multi-stage builds, which allow you to copy only the artifacts you need into the final image. This allows you to include tools and debug information in your intermediate build stages without increasing the size of the final image.
看来最新的Docker版本没有解决处理多层的问题。他们宁愿努力减少最终图像中的数量。最重要的是,文档没有告诉 为什么 许多层都不好。
我知道 AUFS limit 有 42 层。对于广泛使用的图像,保持较小的层数是有意义的,因为它有助于在它们之上构建的其他图像符合限制。但是,还有其他存储驱动程序和图像用于其他目的。
将图像保持较小也很好,原因很明显 - 它们会占用磁盘 space 和网络带宽。但是,我认为
另一方面,许多层允许使用缓存并更快地重建图像。也是平行拉的。
我在一个拥有私有 Docker 注册表的小团队中工作。我们永远不会满足 42 层的限制,主要关心性能和开发速度。
如果是这样,我应该尽量减少 docker 层的数量吗?
我只是想看看 2 个图像有什么区别,一个是用多个 运行 构建的,另一个是用一个 运行 连接命令构建的。
在第一种情况下,图像正在执行一些琐碎的操作(创建和删除文件)。
"single"层图像的内容:
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)。我有 运行 个不同时间的图像,但时间变化不大。
关于 space,我专门针对多层情况下的最坏情况进行了研究,正如预期的那样,多层图像比单层图像大。
在另一项测试中,我连接了仅向图像添加内容的图层。构建时间与之前的情况相比没有变化,但 运行 时间的情况显示出一些不同:多层图像比单层图像启动更快。关于 space,相同的结果。
我不认为这能证明什么,但我在做的过程中很开心:P
I work in a small team with a private Docker registry. We won't ever meet the 42 layers restriction and care mostly about performance and development speed.
如果是这样,我应该尽量减少 docker 层的数量吗?
在你的情况下,没有。
需要最小化的是构建时间,也就是说:
- 确保首先执行最通用和最长的步骤,然后将其缓存,让您可以 fiddle 使用 Dockerfile 的最后几行(最具体的命令),同时有快速的重建时间.
- 确保最长的 运行 命令排在第一位并在它们自己的层中(再次被缓存),而不是与其他 运行 命令链接:如果其中一个失败,长命令将不得不重新执行。如果那个长命令在它自己的(Dockerfile 行)/层中被隔离,它将被缓存。
也就是说,the documentation you mention comes from docker/docker.github.io
, precisely PR 4992 and PR 4854, after a docker build LABEL
section。
所以本节是在关于 LABEL
的类似评论之后出现的,并且只强调创建图层的命令。
同样,在您的情况下,这并不重要。
减少层数本身并不是一个目标。相反,您需要关注的是减少构建时间并减小图像大小。
通过将很少更改的公共层保留在 Dockerfile 的顶部或基础映像中,可以缩短构建时间。这允许在以后的构建中缓存和重用该层。这与减少层数无关,更多的是对层进行排序。
减小图像大小有助于减少注册表服务器上的磁盘使用,当在 CI 系统上为每个构建存储图像时,注册表服务器会看到对磁盘的大量访问。它还减少了传输图像的网络时间。当您有一个下载大型临时文件的层并在另一层删除它时,结果是该文件留在第一层,它通过网络发送并存储在磁盘上,即使它在内部不可见你的容器。更改文件的权限也会导致文件被复制到具有新权限的当前层,使该文件的磁盘 space 和网络带宽加倍。
在上述场景中减小图像大小的标准解决方案是链接 RUN
命令,这样临时文件永远不会存储到图像层。这具有减少图像层数的副作用。
最后一个问题是缓存过多。这在 Debian 映像中的 apt-get update
和 apt-get install ...
命令中很常见。如果您不将这些命令链接在一起,对 apt-get install
命令的更新将重新使用来自前一层 apt-get update
命令的可能过时的缓存,并且在几个月后找不到所需的包时将失败。因此,即使会增加构建时间,您也应该链接这些命令,因为另一个选项是将来构建失败。
所以,更多的是你要的减层的副作用,而不一定是为了减层而减层