For each build command in the Dockerfile, Docker will generate a new filesystem layer.
An image is a combination of all filesystem layers created by the build commands of the Dockerfile.
Each layer is mapped to a specific build command in the Dockerfile.
The size of each filesystem layer depends on the command executed (e.g., adding files, installing libraries, etc.).
The final image size is the sum of the sizes of all its filesystem layers.
Adding commands to delete files created in previous layers does not reduce the final image size,
because each layer is immutable and retained in the image history.
For a new created image, Docker will execute all the build commands in the Dockerfile.
When building an already created image (assuming the cache was not cleared),
Docker uses, for each command in the Dockerfile, the corresponding filesystem layer from its cache, only if:
- The command and its parent were not updated.
- The command and its parent are not generating a new filesystem layer (e.g., new files added or updated, etc.).
If any of the above conditions are not met, Docker will automatically run all build commands in the Dockerfile that are below this updated build command.
Allowing Docker to use cached layers when rebuilding images can significantly reduce build time.
Best practices:
A build command that might create a new filesystem layer every time it's executed (e.g., update OS, library)
should be placed at the bottom of the Dockerfile.
Another option, when possible, is to place that command in a parent Dockerfile and use the generated image as a parent image for the descendant Dockerfiles.
In such case case, the parent image can be re-built only when needed.
Best practices: When possible, multiple build commands should be combined in one single build command (using && operator).
Following best practices when designing Dockerfiles helps:
- speed up the creation of Docker images by leveraging the cache.
- reduce the size of Docker images.
- speed up copying/downloading Docker images by skipping layers that have already been copied/downloaded.
Let's execute again the build command. The output should be similar to the following:
As you can see, Docker verify for each build step if there is a cached layer, and if it does exists, it will use it (see
---> Using cache).
Let's change the Dockerfile a bit (I will change the order of the instructions):
Let's execute the build command. The output should be similar to the following:
As you can notice, the instruction of the step 2 was changed and hence Docker is building a new image layer.
Docker will then execute the subsequent steps and won't use the local cache even if the remaining steps didn't change at all.
Note: You can use the
--no-cache option to instruct Docker not to use the cache from previous builds.