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
&&, 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
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
Some images in which this would help (sorry can’t copy the links as I’m new user):
- Most of the official images…