2017-04-19 73 views
3

在这个官方码头上userguide其中一个建议是最小化Dockerfile中的图层数量。最小化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指令吗?你可以告诉我吗?

回答

4

的Dockerfile “设计”,主要取决于你的需要,你想平衡什么。最小化层数被认为是最佳实践,但正如您已经提到的那样,缓存通过明确创建新图层来工作。有限层数的链接问题可能会成为Docker文件较大的问题,但这也取决于系统上配置的存储驱动程序。你的示例Dockerfile(即使每个脚本都在它自己的RUN声明中)没有达到图层的限制,所以你不必担心。

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

# 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也有助于重新设计保持图像小巧的方式,并减少对脚本的需求。