Docker images are made up of multiple layers that collectively provide the content you see in your containers.
But what exactly is a layer, and how is it different from a full image?
In this article, you’ll learn how to distinguish between the two and why the difference matters.
While you can use Docker without a deep understanding of layers, understanding their purpose will help you identify optimization opportunities.
What is an image?
The Docker image behaves like a template from which sequential containers can be built.
If Docker were a traditional VM, the image could be compared to the ISO used to install the VM.
This isn’t a fair comparison because Docker is different from virtual machines both in concept and implementation, but it’s a useful starting point nonetheless.
The images define the initial file system state of the new containers.
They collect your application’s source code and its dependencies into a self-contained package, ready to be used in a container runtime.
Inside the image, the contents of the file system are represented as several independent layers.
What are layers?
Layers are the result of the way Docker images are built.
Each step in the Dockerfile creates a new “layer”, which is essentially a diff of filesystem changes since the last step.
Metadata instructions such as LABEL and MAINTAINER do not create layers because they do not affect the file system.
This image has two instructions (COPY and RUN), so it will create two layers:
FROM ubuntu:latest COPY foo.txt /foo.txt RUN date > /built-on.txt
The first step copies foo.txt to a new layer based on the ubuntu:latest image.
The second step executes the date command and sends its output to a file.
A second layer is created based on the previous one.
Create a file foo.txt in your working directory:
$ echo "Hello World" > foo.txt
Now let’s build a sample image:
$ docker build . -t demo:latest Sending build context to Docker daemon 2.56kB Step 1/3 : FROM ubuntu:latest ---> df5de72bdb3b Step 2/3 : COPY foo.txt /foo.txt ---> 4932aede6a15 Step 3/3 : RUN date > /built-on.txt ---> Running in 91d260fc2e68 Removing intermediate container 91d260fc2e68 ---> 6f653c6a60fa Successfully built 6f653c6a60fa Successfully tagged foo:latest
At each stage of the assembly, the identifier of the created layer is passed.
The last step layer becomes the final image, so it is labeled foo:latest.
This sequence shows that the layers are valid Docker images.
While the term “layer” is not commonly used to refer to a tagged image, all tagged images are technically just layers with an assigned ID.
You can start the container from the middleware image:
$ docker run -it 4932aede6a15 sh # cat /foo.txt Hello World # cat /built-on.txt cat: /built-on.txt: No such file or directory
This example launches the container from the layer created in the second build step. foo.txt is available in the container, but built-on.txt doesn’t exist because it wasn’t added until the third step.
This file is only available on subsequent layer file systems.
docker pull php:8.0-apache 8.0-apache: Pulling from library/php 7a6db449b51b: Already exists ad2afdb99a9d: Already exists dbc5aa907229: Already exists 82f252ab4ad1: Already exists bf5b34fc9894: Already exists 6161651d3d95: Already exists cf2adf296ef1: Already exists f0d7c5221e44: Pull complete f647198f6316: Pull complete c37afe1da4e5: Pull complete 09c93531cbca: Pull complete fef371007dd3: Pull complete 52043dbb1c06: Pull complete Digest: sha256:429889e8f9eac0a806a005b0728a004303b0d49d77b09496d39158707abd6280 Status: Downloaded newer image for php:8.0-apache docker.io/library/php:8.0-apache
The other layers were already present on the Docker host, so they can be reused.
This improves performance and avoids wasting network bandwidth.
Checking Image Layers
You can view the list of layers in an image by running the docker image history command.
Each layer displays the ID of the created image and the Dockerfile instruction that caused the change.
You can also see the total size of the content in the layer.
$ docker image history IMAGE CREATED CREATED BY SIZE COMMENT 6f653c6a60fa 4 minutes ago /bin/sh -c date > /built-on.txt 29B f8420d1a96f3 4 minutes ago /bin/sh -c #(nop) COPY file:a5630a7506b26a37... 0B df5de72bdb3b 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B 4 weeks ago /bin/sh -c #(nop) ADD file:396eeb65c8d737180... 77.8MB
The last layer is shown as because it refers to a layer in the ubuntu:latest base image.
It is not available locally because only the last layer of the base image (df5de72bdb3b) is demolished during the build.
There is no need to extract all intermediate layers yourself when you want to use a certain image.
Docker images and layers are terms used interchangeably.
A layer is an image, and an image is formed from one or more layers.
The main difference is in the tags: the image will be tagged and intended for end users, while the term “layer” usually refers to untagged intermediate images created during the build process.
They are not visible until you start looking for them.
There is another topic related to layers: running containers add an additional writable layer on top of their image.
Layers created from a container image are read-only, so file system modifications made by a container are directed to its ephemeral writable layer.
The writable layer is discarded when the container is stopped or removed.
#Docker #image #layers #good