最小化Dockerfile中的层数

时间:2017-04-19 12:04:09

标签: docker docker-compose dockerfile

在这个官方泊坞窗userguide中,其中一个建议是最小化Dockerfile中的层数。

我认为它减少了图片的总大小,但发现了有关图层最大限制的内容:Number of commands in Dockerfile

但由于缓存,分割单独的命令非常有用。

例如,有一个像这样的Dockerfile:

# https://hub.docker.com/_/php/
FROM php:5.5.23-fpm

RUN /scripts/base.sh \
 && /scripts/composer.sh \
 && /scripts/mbstring.sh \
 && /scripts/bcmath.sh \
 && /scripts/mcrypt.sh \
 && /scripts/sockets.sh \
 && /scripts/zip.sh \
 && /scripts/phpredis.sh \
 && /scripts/cleanup.sh

这只是一层,所以一旦构建,它就会缓存。但是,如果我改变phpredis的版本,例如,每个步骤将再次构建。

我可以将它们分成单独的RUN指令吗?那你可以告诉我吗?

2 个答案:

答案 0 :(得分:4)

Dockerfile" design"主要取决于您的需求和您想要平衡的内容。最小化层数被认为是最佳实践,但正如您已经提到的,缓存通过显式创建新层来工作。具有有限数量的层的链接问题可能会成为更大的Dockerfiles的问题,但这也取决于系统上配置的存储驱动程序。您的示例Dockerfile(即使每个脚本都在其自己的RUN语句中)也没有达到图层的限制,因此您不必担心。

那就是说,我想你还没有完全理解层缓存是如何工作的(也许你没有发布完整的Dockerfile?)。 Docker不知道脚本在RUN语句中将产生哪些文件系统更改。因此,当您使用精确的Dockerfile重新运行Docker构建时,Docker不会再次运行您的脚本。您提到phpredis版本可能会更改的示例,但Dockerfile并未反映该变量。我建议在相关的ENV语句之前声明一些RUN变量。例如:

# https://hub.docker.com/_/php/
FROM php:5.5.23-fpm

RUN /scripts/base.sh \
 && /scripts/composer.sh \
 && /scripts/mbstring.sh \
 && /scripts/bcmath.sh \
 && /scripts/mcrypt.sh \
 && /scripts/sockets.sh \
 && /scripts/zip.sh \
 && /scripts/cleanup.sh

ENV PHPREDIS_VERSION=1.2.3

RUN /scripts/phpredis.sh \
 && /scripts/cleanup.sh

phpredis.sh应该使用环境变量。每次更改ENV ...语句时,Docker都会在该步骤之后重新运行每个语句,包括phpredis.sh脚本。

也许最近宣布的multi stage builds也有助于重新设计保持图像微小的方式,并减少对cleanup.sh脚本的需求。

答案 1 :(得分:1)

如果您有第二个RUN包含

/scripts/phpredis.sh \ && /scripts/cleanup.sh

第一个RUN将被缓存。

最近的Docker版本如1.13,你有

docker build --squash

参见文档

https://docs.docker.com/engine/reference/commandline/build/#options