Skip to content

Volumes

So far all our files are built into the images. Let's see how we can mount files to containers from the host system, and what we can do with them.

Warning

There are some differences on how Docker (Desktop) works on different Operating Systems.

On Windows and macOS, the Docker daemon is actually running inside a Virtual Machine.

Note

In place of all the curl commands below, you can use a web browser to access the service in the container.

Static web pages for our web server

Docker can mount files from anywhere in the host system to the container.

Let's create some custom content for the NGINX web server we ran earlier.

$ mkdir web
$ echo "Hello world!" > web/hello.txt

Let's run the web server again with the directory mounted.

Note

On Linux and macOS:

$ docker run --rm -v "$PWD/web:/usr/share/nginx/html" -d --name web -p 8080:80 nginx

Note

On Windows (cmd):

$ docker run --rm -v "%cd%/web:/usr/share/nginx/html" -d --name web -p 8080:80 nginx

Here we use the -v option to add a volume mount in format host_path:container_path. We'll use the directory we just created as the host path we want to mount, and /usr/share/nginx/html as the target path in the container. In this case, the target path is the place where NGINX serves static files from.

Note that the host path must be specified as an absolute path, which is why the example uses the $PWD environment variable or %cd% on Windows.

Let's see if we can access the file we just created and mounted.

$ curl http://localhost:8080/hello.txt
Hello world!

You may notice, that the earlier index.html file served by NGINX in the root does not work any more!

This is because we bind mounted the whole web/ directory on top of /usr/share/nginx/html in the container.

To share just one file, specify it explicitly:

$ docker stop web

Note

On Linux and macOS:

$ docker run --rm -v "$PWD/web/hello.txt:/usr/share/nginx/html/hello.txt" -d --name web -p 8080:80 nginx

Note

On Windows (cmd):

$ docker run --rm -v "%cd%/web/hello.txt:/usr/share/nginx/html/hello.txt" -d --name web -p 8080:80 nginx

Very cool! Let's clean up the resources.

$ docker stop web

Persisting state

The mount we created earlier is called a bind mount. We can also create dedicated, persistent volumes that are managed by Docker, and mount them to containers. They are primarily used for ensuring critical data written by the containers is persisted safely. For example, the local Docker registry can use volumes to store the published images.

Let's create our own volume!

$ docker volume create mystuff

$ docker volume ls
DRIVER      VOLUME NAME
local       mystuff

The name of our volume is mystuff. By default, it uses a local driver, which means that all the data is stored in a host directory. We could also use an alternative driver that stores the data in a different way.

Let's mount the volume to a plain Ubuntu container, and use the container to write some data to the volume. We'll install and run a toy program called cowsay to generate an ASCII picture to a file named message.txt in the volume. We can mount the volume using its name.

$ docker run --rm -v mystuff:/data ubuntu:20.04 \
    bash -c 'apt-get update && apt-get install -y cowsay && /usr/games/cowsay Hello world! > /data/message.txt'

We should now have a file in the mystuff volume.

Using the command docker volume inspect, we can see the location of the volume files on the host system. On Linux, we can access the files directly, but on Mac and Windows the files are stored inside the virtual machine that runs Docker and containers.

$ docker volume inspect mystuff
[
    {
        "CreatedAt": "2019-02-02T22:58:46+02:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mystuff/_data",
        "Name": "mystuff",
        "Options": {},
        "Scope": "local"
    }
]

We can also re-mount the volume to another container to read the data there. Let's serve the stored file via a web server.

$ docker run --rm -v mystuff:/usr/share/nginx/html -d --name web -p 8080:80 nginx

$ curl http://localhost:8080/message.txt
 ______________
< Hello world! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ docker stop web

Great! Let's clean up the environment and delete the volume.

$ docker volume rm mystuff

Next

In the next section, we'll learn how networking with containers works.