Docker Image Layers

Docker Image Layers

In this tutorial we will discuss about Docker image layers and how intermediate layers are created, and how dangling images are destroyed.

When you pull a Docker image, you will notice that it is pulled as different layers. Also, when you create your own Docker image, several layers are created.

A Docker image consists of several layers. Each layer corresponds to certain instructions in your Dockerfile.

The following instructions create a layer: RUN, COPY, ADD. The other instructions will create intermediate layers and do not influence the size of your image.

Layers of a Docker image are essentially just files generated from running some command. All of the information about the docker image and container layers is stored in sub directories of /var/lib/docker/aufs/.

Docker image layers are neat because they can be re-used by multiple images saving disk space and reducing time to build images while maintaining their integrity.

A Docker image consists of read-only layers each of which represents a Dockerfile instruction. The layers are stacked and each one is a delta of the changes from the previous layer.

Let’s look at the following Dockerfile

FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py

Each instruction creates one layer:

  • FROM creates a layer from the ubuntu:18.04 Docker image.
  • COPY adds files from your Docker client’s current directory.
  • RUN builds your application with make.
  • CMD specifies what command to run within the container.

When you run an docker image and generate a container, you add a new writable layer (the “container layer”) on top of the underlying layers.

All changes made to the running container, such as writing new files, modifying existing files, and deleting files, are written to this thin writable container layer.

Docker Image Layers

When the container is stopped writable layer remains, and if container was removed writable layer is deleted. So that’s why people say, containers are stateless.

Example

For example, here is a Dockerfile for creating a node.js web app image. It shows the commands that are executed to create the image.

When Docker builds the container from the above Dockerfile, each step corresponds to a command run in the Dockerfile.

Docker image layers are made up of the file generated from running that command. Along with each step, the layer created is listed represented by its random generated ID.

For example, the layer ID for step 1 is 850d74a0344f.

$ docker build -t mywebapp .
Step 1 : FROM node:argon
argon: Pulling from library/node...
...
Status: Downloaded newer image for node:argon
 ---> 850d74a0344f
Step 2 : RUN mkdir -p /usr/src/app
 ---> Running in 5090fde23e44
 ---> 8184cc184ef8
Removing intermediate container 5090fde23e44
Step 3 : WORKDIR /usr/src/app
 ---> Running in 2987746b5fba
 ---> 96c81d89b023
Removing intermediate container 2987746b5fba
Step 4 : COPY package.json /usr/src/app/
 ---> 773d93a151ee
Removing intermediate container a678c817e467
Step 5 : RUN npm install
 ---> Running in 31ee9721cccb
 ---> ecf7275feff3
Removing intermediate container 31ee9721cccb
Step 6 : COPY . /usr/src/app
 ---> 995a21532fce
Removing intermediate container a3b7591bf46d
Step 7 : EXPOSE 8080
 ---> Running in fddb8afb98d7
 ---> e9539311a23e
Removing intermediate container fddb8afb98d7
Step 8 : CMD npm start
 ---> Running in a262fd016da6
 ---> dff93d9c2c60
Removing intermediate container a262fd016da6
Successfully built dff93d9c2c60

Once the image is built, you can view all the layers that make up the image with the docker history command.

The “Image” column (i.e intermediate image or layer) shows the randomly generated UUID that correlates to that layer.

$ docker history expressweb
IMAGE         CREATED    CREATED BY                       SIZE      
dff93d9c2c60  2 days ago /bin/sh -c CMD ["npm" "start"]   0 B
e9539311a23e  2 days ago /bin/sh -c EXPOSE 8080/tcp       0 B
995a21532fce  2 days ago /bin/sh -c COPY dir:50ab47bff7   760 B
ecf7275feff3  2 days ago /bin/sh -c npm install           3.439 MB
773d93a151ee  2 days ago /bin/sh -c COPY file:551095e67   265 B
96c81d89b023  2 days ago /bin/sh -c WORKDIR /usr/src/app  0 B
8184cc184ef8  2 days ago /bin/sh -c mkdir -p /usr/src/app 0 B
850d74a0344f  2 days ago /bin/sh -c CMD ["node"]          0 B

The docker image history doesn’t always show uniform information e.g., when you pull the image from the docker hub instead of creating it locally.

For this reason you can use a tool called, Dive tool which takes care of various scenarios and shows a uniform output.

Dangling images

Dangling images are layers that have no relationship to any tagged images. They no longer serve a purpose and consume disk space.

Dangling images are created while creating new build of a image without renaming/updating the version of the image. So that the old image are converted into dangling images.

List Dangling images

$ docker images -f dangling=true

Remove Dangling images

$ docker rmi $(docker images -f dangling=true -q)
Docker Image Layers
Scroll to top