Understanding the process Docker uses to store data through images and containers will help you better design your Docker applications. Docker images are like templates while Docker containers are the running instances created from those templates. Docker uses a layered approach to storing images and containers.
Images and Layers
A Docker image is created from multiple layers. If we take an example of a Dockerfile, every instruction is converted to a layer. Here is a simple Dockerfile:
FROM node:6.9.2 COPY server.js . CMD node server.js
Every line in the above Dockerfile will create a layer. The FROM statement will look for the node:6.9.2 image in the local registry. If it doesn’t find it there, then it will download it from the Docker Hub. Then Docker will create the first layer. The next COPY statement adds the server.js file to the image as a second layer. The last layer runs a Node.js application. All these layers are stacked on top of each other. Each additional layer is added as a difference from the layer before it.
Containers and Layers
Containers are created from images. When a container is created from an image, a thin read/write layer is put on top of the image (Notice that image layers are immutable, container layers are not). Any changes made to the container is put on this read/write layer during the lifetime of the container. When a container is deleted, the associated thin read/write layer is removed. It means that multiple containers can share the same image. Each container layer will maintain its own data safely on top of the Docker image.
Images and Containers
Let’s try a simple example. You can use the docker images command to find all the images:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE
And the docker ps command to find containers:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
This is a fresh docker installation. So there is no image or container present. You can run the docker run -it node:6.9.2 command to start a container.
$ docker run -it node:6.9.2 Unable to find image 'node:6.9.2' locally 6.9.2: Pulling from library/node 75a822cd7888: Pull complete 57de64c72267: Pull complete 4306be1e8943: Pull complete 871436ab7225: Pull complete 0110c26a367a: Pull complete 1f04fe713f1b: Pull complete ac7c0b5fb553: Pull complete Digest: sha256:2e95be60faf429d6c97d928c762cb36f1940f4456ce4bd33fbdc34de94a5e043 Status: Downloaded newer image for node:6.9.2 >
Now if we again check the Docker images, we find:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE node 6.9.2 faaadb4aaf9b 11 months ago 655MB
And if we check container, we find:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8c48c7e03bc7 node:6.9.2 "node" 20 seconds ago Up 18 seconds reverent_jackson
If we start another container from the same image using the command:
$ docker run -it node:6.9.2
And check again, we see:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE node 6.9.2 faaadb4aaf9b 11 months ago 655MB
And
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 96e6db955276 node:6.9.2 "node" 24 seconds ago Up 23 seconds cocky_dijkstra 8c48c7e03bc7 node:6.9.2 "node" 4 minutes ago Up 4 minutes reverent_jackson
The two containers with CONTAINER ID 96e6db955276 and 8c48c7e03bc7 are both running on top of the Docker image with the IMAGE ID faaadb4aaf9b. The thin read/write layers of the Docker containers are residing on top of the layer of the Docker image.
Hints:
You can remove Docker containers with the command docker rm [CONTAINER ID] and remove Docker images with the command docker rmi [IMAGE ID].
The image node:6.9.2 we downloaded from Docker Hub is also created by combining multiple layers. You can check the layers of images using docker history [IMAGE ID].
$ docker history faaadb4aaf9b IMAGE CREATED CREATED BY SIZE faaadb4aaf9b 11 months ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 11 months ago /bin/sh -c curl -SLO "https://nodejs.org/d 42.5MB <missing> 11 months ago /bin/sh -c #(nop) ENV NODE_VERSION=6.9.2 0B <missing> 11 months ago /bin/sh -c #(nop) ENV NPM_CONFIG_LOGLEVEL 0B <missing> 11 months ago /bin/sh -c set -ex && for key in 955 108kB <missing> 11 months ago /bin/sh -c groupadd --gid 1000 node && u 335kB <missing> 11 months ago /bin/sh -c apt-get update && apt-get insta 323MB
Conclusion
A popular way of explaining images and containers is to compare an image to a class and a container to the instance of that class. The layered approach of docker images and containers helps keep the size of images and containers small.