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:
FROMcreates a layer from the
COPYadds files from your Docker client’s current directory.
RUNbuilds your application with
CMDspecifies 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.
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.
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
$ 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 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)