Minimizing the number of layers in the Dockerfile

In this official docker userguide, one of the tips was to minimize the number of layers in the Dockerfile.

I thought this reduced the overall image size, but found something about the maximum limit of layers: Number of commands in Dockerfile

But it is very useful to separate separate commands because of caching.

For example a has a Dockerfile like:

# 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 after it is created it will cache. But if I change the phpredis version, for example, every step is built again.

Can I split them into separate RUN instructions? What can you advise me?

+3


source to share


2 answers


Dockerfile "design" mainly depends on your needs and what you want to balance. Minimizing the number of layers is considered best practice, but as you mentioned, caching works by explicitly creating a new layer. The associated layer limited issue can be a problem for large Dockerfiles, but it also depends on the configured storage driver on your system. Your Dockerfile example (even with each script in its own expression RUN

) doesn't reach the layer limit, so you don't have to worry.

However, I suppose you are not quite clear on how layer caching works (perhaps you haven't posted the complete Dockerfile?). Docker doesn't know which filesystem will modify your scripts at runtime RUN

. Hence, when you rerun a Docker build with this exact Dockerfile, Docker will not run your scripts again. You mentioned as an example that the phpredis version may change, but the Dockerfile does not reflect this variable. I suggest declaring some variable ENV

before the corresponding statement RUN

. 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

      



phpredis.sh

should use an environment variable. Every time you change a statement ENV ...

, Docker will rerun every statement after that step, including your phpredis.sh

script.

Perhaps the recently announced multistage builds will also help redesign the way you save your images and reduce the need for a cleanup.sh

script.

+4


source


if you have a second RUN containing

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

the first RUN will be cached.

In latest docker versions like 1.13 you have



docker build --squash

see document

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

+1


source







All Articles