Containers are significant to application management since they allow your applications to run reliably and consistently on any infrastructure environment or operating system. Docker images are mainly responsible for shipping, storing, and delivering containerized applications. Docker images are your starting point if you are a first-time Docker user. However, these images are a composition of different Docker image layers.
Containers are created using read-only templates referred to as Docker images. These images consist of several layers combined into a single virtual file system. While Docker images are immutable, you can add extra layers and save them as new images. You can change or add content in a Docker image without changing the image directly but to the individual Docker image layers.
In this article, we discuss what Docker images are, why Docker image layers are important, Docker image anatomy, and use cases.
What Are Docker images?
Applications consist of Docker containers as the main building blocks, with each container representing an image (Docker image). Docker images are built up of layers stacked up, one on top of the other. Docker reads instructions from Dockerfile to build images automatically. It does so using the Docker build command feature.
Each Docker image layer represents an instruction in the Dockerfile. A Dockerfile refers to a text document consisting of all the commands required to assemble an image. Only the top layer of Docker images has read-write permissions; the rest have read-only permissions. Like the copy-on-write concept, this technology ensures that the changes you make when running a container from the image are made to the top writable layer.
Why Docker Image Layers Are Important
Docker image layers are beneficial in many ways.
- Layers allow you to work with Docker images faster. This is because the builds avoid unnecessary steps, and the pulling and pushing of images skips the transfer of a large unchanged amount of data already available in the intended destination.
- The use of the copy-on-write file system saves disk space for future containers and images.
- Layers allow you to apply less computational effort (in image building) and save on bandwidth (in image distribution).
Docker Image Layers
Images contain everything you need to configure and run a container environment. These include system libraries, dependencies, and tools.
Docker images consist of many layers. Each layer is built on top of another layer to form a series of intermediate images. This arrangement ensures that each layer depends on the layer immediately below it. The way layers are placed in a hierarchy is very significant. It allows you to place the layers that frequently change high up the hierarchy so that you manage the Docker image’s lifecycle efficiently.
Changes made to a Docker image layer trigger Docker to rebuild that particular layer and all other layers built from it. Making changes to a layer at the top of the stack ensures the rebuilding of the entire image using fewer computational resources. This means you should keep the layers with the least or no changes at the bottom of the hierarchy formed.
To understand this concept in detail, let’s take an example. Assume you have a Node.js app and want to create a Docker image for this app. Below is the most basic Dockerfile that you can use to create the Node.js image:
FROM node:alpine WORKDIR /app COPY package*.json ./ RUN npm install COPY ./ ./ CMD ["npm", "start"]
This Dockerfile contains instructions needed to build a basic Node.js app image on Docker. When you run a docker build
command, Docker starts executing these instructions one at a time, iteratively.
Docker Commands
First, it will read the FROM
command and execute a Node.js image as the base image from the Docker registry. A base image provides the environment to run the application of your choice just the same way you would on a local machine.
It is good to note that a base image will have its own image layers based on how it was initially created and deployed to the Docker Hub registry.
Once Docker gets the base image, it moves to the next command, WORKDIR
. At this point, the Docker build context will create an intermediate image. This process creates a new image layer by committing a new intermediate image. Here is a diagram that illustrates this example:
Each time a command is executed from the Dockerfile, a new image layer is created on top of the existing image. This process is iterated until Docker reads the last command of the Dockerfile. Each instruction created a new image.
At the end of the day, Docker will have created the whole image. However, these images are a composition of different image layers, as illustrated above.
This is how Docker will execute the instruction in a typical interactive terminal:
Docker Image Layers Mutability
The composition of a Docker image is mutable, so you can change it. However, these changes are dependent on the image layer. Docker builds the image based on the layer that has the latest changes.
As we explained earlier, changes made to a Docker image layer trigger Docker to rebuild that particular layer and all other layers built from it. You should keep the layers with the least or no changes at the bottom of the hierarchy formed.
If you rebuilt the above images with no changes in them, each one of these layers could be built from the cache. Docker can recognize any changes. Let’s say it happens that you have introduced a change to your Dockerfile. Explicitly adding a new package to the package.json
to the already exciting application. In this case, COPY package*.json ./
will be triggered with new changes. Docker will be required to rebuild the relevant image layer to add the new changes.
However, it’s good to note that based on the image hierarchy, The layer below COPY package*.json ./
will be executed from the cache since no changes will be detected to them. Once COPY package*.json ./
triggers new changes, all the layers above will be rebuilt. Here is an example of a typical image rebuild:
The same should happen if, let’s say you, added new code to the application. And in this case, the rebuild changes will be triggered from COPY ./ ./
up:
Compositions of a Docker image
Typically, an image can constitute the following:
- Base image
All of the container images are created from the base image. This is an empty first layer that allows users to build their first Docker images from scratch. If you do not want to create your base image from scratch, you can use an official Docker image like Centos as your base image or customize one of the official Docker images to your requirements.
- Parent image
The parent image is, in most cases, the first Docker image layer. This is the foundation of all other layers in your Docker. Thus, this layer provides the basic building blocks for container environments.
- Layers
The other Docker layers are added to the base image using a code to allow them to run in a container. Docker’s default status displays all the top-layer images, including file sizes, tags, and repositories. Caching of intermediate layers makes it easier to view the top layers. Storage drives in Docker manage the contents in image layers.
- Container layer
Besides creating a new container, a Docker image creates a container or writable layer. It hosts the changes that you make to your running container. This layer also stores the deleted and newly written files and changes made to the existing files. This layer is also useful when customizing containers.
- Docker manifest
The list of all image layers created by specific image names is known as a Docker manifest. These manifests are used the same way you would use an image name in the docker run
and pull
commands.
Conclusion
Docker images provide users with everything they require to run containerized apps. These include environmental variables, config files, and code. You can execute images deployed to Docker environments as Docker containers. You need to execute the docker run command to create a container from an image of your choice. Docker images are both reusable and deployable on any host. This allows you to use static image layers of a particular project in another project. This helps to avoid recreating images from scratch and saves time.
This article has introduced us to the basics of the Docker image and its layers. Understanding various Docker image layers concepts is critical before starting to build your first Docker image.