volumes tmpfs and binds

November 15, 2021 - Reading time: 4 minutes

The union file system (UnionFS) that inspired overlay2, aufs shouldn't be used to write files that need to out-live the container (like databases, logs) or data that needs to be shared with other containers or with the host.

A container can have access at the same type to all type of storage (mounted with --mount). For example:

Image FS --> overlay driver --> Maps to /var/lib/docker/overlay2/l/... in the host
In-Memory --> tmpfs --> volatile /tmp on the container
Bind-mount --> /etc/httpd/test.conf --> Maps to /home/test/nginxconf.txt in the host (ro or rw)
Volume --> /var/logs --> Maps to /var/lib/docker/volumes/some-location/_data (read/write)

Bind

I can link a specific file or folder on the host system to the container. This is useful for logs, config files, or any other tool that needs to be shared between the host and the container. src represents the file in the host:

CONF_SRC=~/example.conf; \
CONF_DST=/etc/nginx/conf.d/default.conf; \

LOG_SRC=~/example.log; \
LOG_DST=/var/log/nginx/custom.host.access.log; \

docker run -d --name diaweb \
  --mount type=bind,src=${CONF_SRC},dst=${CONF_DST} \
  --mount type=bind,src=${LOG_SRC},dst=${LOG_DST} \
  -p 80:80 \
  nginx:latest

The bind replaces the original content of the image in /etc/nginx/conf.d/default.conf - Optionally the bind can be made Read-only

In-mem

Useful for private keys, API keys, passwords or any private information.

docker run --rm \
    --mount type=tmpfs,dst=/tmp \
    --entrypoint mount \
    alpine:latest -v
[...]
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noexec,relatime)

We can add more parameters to limit the size, and the file permissions.

Volumes

Useful to share locations between different containers. The volumes could be local to the host, or remote (specified by the driver option). Volumes can be created on their own, or as part of a container, listed and inspected.

test@localhost: sudo docker volume create --driver local --label test=first myvolume
myvolume
test@localhost: sudo docker volume inspect myvolume 
[
    {
        "CreatedAt": "2021-11-15T12:06:32Z",
        "Driver": "local",
        "Labels": {
            "test": "first"
        },
        "Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
        "Name": "myvolume",
        "Options": {},
        "Scope": "local"
    }
]

Volumes can be passed to containers with --volume or with mount (type=volume).

test@localhost: sudo docker run -d --volume myvolume:/var/lib/cassandra/data --name cass1 cassandra:2.2 
[...]
test@localhost: sudo docker exec -it cass1 /bin/sh
# cqlsh 
cqlsh> create keyspace docker_hello_world
   ... with replication = {
   ...     'class' : 'SimpleStrategy',
   ...     'replication_factor': 1
   ... };

The content is now saved in a volume. Even if the container is deleted, a new cassandra container can be launched with the same volume settings to access the data.
Containers can use the --volumes-from flag to copy existing volumes from other containers