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?
source to share
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.
source to share
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
source to share