简体   繁体   English

最小化Dockerfile中的层数

[英]Minimizing the number of layers in Dockerfile

In this official docker userguide one of the advise was minimizing the number of layers in Dockerfile. 在这个官方docker用户指南中,其中一个建议是最小化Dockerfile中的层数。

I thought that it is decrease the total size of an image, but found something about the max limit of layers: Number of commands in Dockerfile 我认为它减少了图像的总大小,但发现了一些关于图层的最大限制: Dockerfile中的命令数

But it is very helpful to divide separate commands because of caching. 但由于缓存,分割单独的命令非常有用。

For example, a have a Dockerfile like this: 例如,有一个像这样的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

This is only one layer, so once been built, it will cache. 这只是一层,所以一旦构建,它将缓存。 But if I change the version of phpredis for example, each steps will build again. 但是,如果我改变phpredis的版本,例如,每个步骤将再次构建。

Can I divide them into separate RUN instructions? 我可以将它们分成单独的RUN指令吗? That can you advise to me? 那你可以告诉我吗?

The Dockerfile "design" mainly depends on your needs and what you want to balance. Dockerfile“设计”主要取决于您的需求和您想要平衡的内容。 Minimising the number of layers is considered to be a best practice, but as you already mentioned, caching works by explicitly creating a new layer. 最小化层数被认为是最佳实践,但正如您已经提到的,缓存通过显式创建新层来工作。 The linked issue with a limited number of layers might become a problem with bigger Dockerfiles, but that also depends on the configured storage driver on your system. 具有有限数量的层的链接问题可能会成为更大的Dockerfiles的问题,但这也取决于系统上配置的存储驱动程序。 Your example Dockerfile (even with each script in its own RUN statement) doesn't reach the limit of layers, so you don't need to worry. 您的示例Dockerfile(即使每个脚本都在自己的RUN语句中)也没有达到图层的限制,因此您不必担心。

That said, I suppose you didn't fully understand how the layer caching works (maybe you didn't post the complete Dockerfile?). 也就是说,我想你没有完全理解层缓存是如何工作的(也许你没有发布完整的Dockerfile?)。 Docker doesn't know which file system changes your scripts will produce during a RUN statement. Docker不知道脚本在RUN语句期间将生成哪些文件系统更改。 Consequently, when you re-run the Docker build with that exact Dockerfile, Docker won't run your scripts again. 因此,当您使用精确的Dockerfile重新运行Docker构建时,Docker将不再运行您的脚本。 You mentioned as example that the phpredis version might change, but the Dockerfile doesn't reflect that variable. 您提到示例phpredis版本可能会更改,但Dockerfile不会反映该变量。 I suggest to declare some ENV variable before the relevant RUN statement. 我建议在相关的RUN语句之前声明一些ENV变量。 Example: 例:

# 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

The phpredis.sh should use the environment variable. phpredis.sh应该使用环境变量。 Every time you change the ENV ... statement, Docker will re-run every statement after that step, including your phpredis.sh script. 每次更改ENV ...语句时,Docker都会在该步骤之后重新运行每个语句,包括phpredis.sh脚本。

Maybe the recently announced multi stage builds also help to re-design the way you keep your images tiny and reduces the need for the cleanup.sh script. 也许最近宣布的多阶段构建也有助于重新设计保持图像微小的方式,并减少对cleanup.sh脚本的需求。

if you have a second RUN containing 如果你有第二个RUN包含

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

the first RUN will be cached. 第一个RUN将被缓存。

With recent docker versions like 1.13, you have 最近的Docker版本如1.13,你有

docker build --squash

see the doc 看文件

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM