on
Docker 101 - Layers
In this article, we will learn how Docker handles Layers to create images and containers.
Docker Guide (6 Part Series)
- Docker Containers
- Docker Images
- Docker Layers
- Docker with Java Spring and Maven
- Understand Dockerfile Volume
- Docker Builder Containers
Terminology
The basic concepts of Docker are Images and Containers:
- Image: Ordered collection of filesystem changes and execution parameters
- Container: Runtime instance of a docker image
There are other concepts to know about :
- Volume: System to persist data, independent of the container’s life cycle
- Dockerfile: Text document that contains all the commands to create an image
- Layer: modification to an image, represented by an instruction in the Dockerfile
- Tag: Label applied to a Docker image in a repository.
- Repository: Set of Docker images
- Registry: Hosted service containing repositories of images
- Union File System: conjunction with copy-on-write techniques to provide the building blocks for containers
What are the layers?
While running a container, Docker CLI logs the executed actions one by one and among the logs, many lines are starting with an ID and telling “Pull complete”:
node1] (local) root@192.168.0.18 ~
$ docker pull debian
Using default tag: latest
latest: Pulling from library/debian
952936b044f5: Pull complete
de09a6a5e5cb: Pull complete
Digest: sha256:e2164514055ae7bc19...
Status: Downloaded newer image for debian:latest
docker.io/library/debian:latest
What is this?
According to the documentation, Docker images can consist of multiple layers. So when we pull an image, it pulls one or many layers. In the example above, the image consists of two layers; 952936b044f5
and de09a6a5e5cb
. So These images are not just one monolithic block but are composed of many layers. The first layer in the image is also called the base layer.
For example, we can create an image based on debian
and install nodejs
:
FROM debian
RUN apt-get install -y nodejs
docker build -t node_debian_image .
Once the image is built, you can view all the layers that make up the image with the docker history command.
docker history node_debian_image
IMAGE CREATED CREATED BY SIZE
93d92c6cfdd0 2d ago /bin/sh -c RUN apt-get install -y nodejs 28MB
b7c5e11b4e6e 5w ago /bin/sh -c #(nop) ADD file:4f5e3fbdf4… 114MB
The result of our image will be two layers: firstly, the base layer from debian
, and secondly, a layer with a command to install nodejs
.
+-----------------------------------------------+
| +-------------------------------------------+ |
| | Layer 1 - RUN apt-get install -y nodejs | |
| +-------------------------------------------+ |
| +-------------------------------------------+ |
| | Base Layer - FROM debian | |
| +-------------------------------------------+ |
| == Image "node_debian_image" == |
+-----------------------------------------------+
So, layers are essentially just files generated from running some commands and these commands are nothing but files that will be stacked in this image.
All layers of an image are immutable or read-only which means once created can’t be changed but we can delete it.
When we launch a container from an image, Docker adds a read-write layer to the top of that stack of read-only layers. Docker calls this the Union File System:
docker run --name node_debian_container node_debian_image
+--------------------------------------------------------------+
| +-----------------------------------------+ |
| | Container Layer | +---> Read-Write |
| +-----------------------------------------+ |
| +-----------------------------------------+ |
| | Layer 1 - RUN apt-get install -y nodejs | +---> Read-Only |
| +-----------------------------------------+ |
| +-----------------------------------------+ |
| | Base Layer - FROM debian | +---> Read-Only |
| +-----------------------------------------+ |
| == Container "node_debian_container" == |
+--------------------------------------------------------------+
By doing this, the same immutable image can be used across various applications just by adding a single writable docker layer. node_debian_image
can be used to run web apps.
Let’s modify this image and run a web application inside.
The new Dockerfile will use the previous image as a base:
FROM node_debian_image
COPY server.js /usr/src/app
CMD [ "node", "server.js" ]
The example is package in server.js
file. Let’s build the image and see the result.
docker build -t node_debian_server_image .
+---------------------------------------------+
| +-----------------------------------------+ |
| | Layer 2 - COPY server.js /usr/src/app | |
| | CMD [ "node", "server.js" ] | |
| +-----------------------------------------+ |
| +-----------------------------------------+ |
| | Layer 1 - RUN apt-get install -y nodejs | |
| +-----------------------------------------+ |
| +-----------------------------------------+ |
| | Base Layer - FROM debian | |
| +-----------------------------------------+ |
| == Image "node_debian_server_image" == |
+---------------------------------------------+
Let’s run and see the result:
docker run --name node_debian_server_container node_debian_server_image
+----------------------------------------------------------------+
| +-------------------------------------------+ |
| | Container Layer server.js | +---> Read-Write |
| | ^ | |
| +-------------------------------------|-----+ |
| | <-----+ File mapping |
| +-------------------------------------|-----+ |
| | | | +---> Read Only |
| | Layer 2 - COPY server.js /usr/src/app | |
| | CMD [ "node", "server.js" ] | |
| +-------------------------------------------+ |
| +-------------------------------------------+ |
| | Layer 1 - RUN apt-get install -y nodejs | +---> Read Only |
| +-------------------------------------------+ |
| +-------------------------------------------+ |
| | Base Layer - FROM debian | +---> Read Only |
| +-------------------------------------------+ |
| == Image "node_debian_server_container" == |
+----------------------------------------------------------------+
Any time a file is changed, Docker makes a copy of the file from the read-only layers up into the top read-write layer. This leaves the original (read-only) file unchanged.
When a container is deleted, the top read-write layer is lost. This means that any changes made after the container was launched are now gone.
This system helps to save disk space and reducing time to build images while maintaining their integrity. These layers (also called intermediate images) are generated when the commands in the Dockerfile are executed during the build.
Conclusion
In this article, we discussed Docker layers and how images and containers are created.