Layers, images, containers, and volumes

We know that an image is immutable and a container is ephemeral, and we know how to run an image as a container. Nevertheless, we are still missing some information with regard to packing an image.

An image is a read-only stack that consists of one or more layers, and a layer is a collection of files and directories in the filesystem. To improve disk space utilization, layers aren't locked to just one image but are shared among images, which means that Docker simply stores one copy of a base image locally, regardless of how many images are derived from it. You can utilize the docker history [image] command to understand how an image is built. For example, you will see that Alpine has only one layer if you check it with docker history alpine.

Whenever a container is created, it adds a thin, writable layer on top of the base image. Docker adopts the Copy-On-Write (COW) strategy on the thin layer. This means that a container reads the layers of the base image where the target files are stored and copies the file to its own writable layer if the file is modified. This approach prevents containers that are created from the same image from intervening with each other. The docker diff [CONTAINER] command shows the difference between the container and its base image in terms of their filesystem states. For example, if /etc/hosts in the base image is modified, Docker copies the file to the writable layer, and it'll be the only file in the output of docker diff.

The following diagram illustrates the hierarchical structure of Docker images:

It's important to note that data in the writable layer is deleted along with its container. To persist data, you commit the container layer as a new image with the docker commit [CONTAINER] command or mount data volumes into a container.

A data volume allows a container to carry out reading and writing operations, bypassing Docker's filesystem. It can either be on a host's directory or in other storage, such as Ceph or GlusterFS. Therefore, any disk I/O against the volume can operate at native speeds depending on the underlying storage. Since the data is persistent outside a container, it can be reused and shared by multiple containers. Mounting a volume is done by specifying the -v (--volume) flag with docker run or docker create. The following example mounts a volume under /chest in the container and leaves a file there. Afterwards, we use docker inspect to locate the data volume:

$ docker run --name demo -v /chest alpine touch /chest/coins
$ docker inspect demo ## or filter outputs with --format '{{json .Mounts}}'
...
"Mounts": [
{
"Type": "volume",
"Name":"(hash-digits)",
"Source": "/var/lib/docker/volumes/(hash-digits)/_data",
"Destination": "/chest",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
$ ls /var/lib/docker/volumes/(hash-digits)/_data
coins
The default tty path of the micro Linux provided by Docker CE on macOS can be found in the following location:
~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty.
You can attach to it with screen.

One use case of data volumes is sharing data between containers. To do this, we first create a container and mount volumes on it, and then reference the volume with the --volumes-from flag when launching other containers. The following examples create a container with a data volume, /share-vol. Container A can put a file into it, and container B can read it:

$ docker create --name box -v /share-vol alpine nop
7ed7c0c4426df53275c0e41798923121093b67d41bec17d50756250508f7b897
$ docker run --name AA --volumes-from box alpine touch /share-vol/wine
$ docker run --name BB --volumes-from box alpine ls /share-vol
wine

In addition, data volumes can be mounted under a given host path, and of course the data inside is persistent:

$ docker run --name hi -v $(pwd)/host/dir:/data alpine touch /data/hi
$ docker rm hi
$ ls $(pwd)/host/dir
hi
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset