An idea I got in my mind since a little while.
Every time you build an image from a Dockerfile, each instruction will create a new layer. That’s a great way to leverage caching and reusability of layers amongst different projects.
However, keeping the number of layers small can be a bit challenging. For instance, if you need to install multiple shell commands, you need to call RUN for each command, leading to a significant number of addition and unnecessary layers. You can separate each command with ; or &&, to have all your commands in one unique layers, making it harder to read and maintain.
Example for the Docker Whalesay (https://hub.docker.com/r/docker/whalesay/)
FROM ubuntu:14.04
# install cowsay, and move the "default.cow" out of the way so we can overwrite it with "docker.cow"
RUN apt-get update && apt-get install -y cowsay --no-install-recommends && rm -rf /var/lib/apt/lists/* \
&& mv /usr/share/cowsay/cows/default.cow /usr/share/cowsay/cows/orig-default.cow
# ...
My idea would be to wrap RUN commands inside blocks, defining explicitly what the layer is.
It would give something like this:
FROM ubuntu:14.04
LAYER # Create one single layer
RUN apt-get update
RUN apt-get install -y cowsay --no-install-recommends
RUN rm -rf /var/lib/apt/lists/
RUN mv /usr/share/cowsay/cows/default.cow /usr/share/cowsay/cows/orig-default.cow
ENDLAYER # End of the layer
or
FROM ubuntu:14.04
LAYER # Create one single layer
|RUN apt-get update
|RUN apt-get install -y cowsay --no-install-recommends
|RUN rm -rf /var/lib/apt/lists/
|RUN mv /usr/share/cowsay/cows/default.cow /usr/share/cowsay/cows/orig-default.cow
RUN echo "I'm not part of the layer because I don't start with a pipe"
This will allow more readable images, easier to write, read and maintain. I think it would be also useful to have this idea for CP or ADD.
Some images in which this would help (sorry can’t copy the links as I’m new user):
- MariaDB
- MongoDB
- Redis
- Ruby
- Most of the official images…