Docker basics: sharing storage between containers and hosts using docker bind mounts

In the last article, we've learned that we can separate the container lifecycle and the lifecycle of the storage. We know that volume can be separate in the computer host, so they're decoupled from the container. But there's also another way to separate volume and container and share the data from the host using the bind mounts. To explain it simply, bind mounts make it possible for our container to access a directory directly to our host directory and vice versa.

Using the docker bind mounts

The bind mounts let us explicitly use the filesystems on our host machine for the container data. As long as we can access that filesystem on our host, we can also use it for containers. Form this alone we can see that bind mounts serve a different purpose than docker volume.

So here's how we start a container with a bind mounts in our terminal/CMD from docker docs :

docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest

We can see that all that command above did is just running a nginx:latest image interactively in the background using detach and it command also giving it a name "devtest" using --name tag.

But the difference here is, there's a new tag --mount. As we can see from the tag, we know that it was a tag that does the bind mounts for us. The tag consists of multiple key-value pairs, separated by commas and each consisting of a key=value tuple. The --mount syntax is more verbose than -v or --volume, but the order of the keys is not significant, and the value of the flag is easier to understand.

The key type from the mount tag can have the value of bind, volume, or tmpfs. But because we're talking about bind mounts, so the type here is bind.

The key source from the mount tag is for the path to the file or directory on the Docker daemon host (our host pc). This key may also be specified as source or src.

The key target from the mount tag is the path where the file or directory is mounted in the container. This key may be specified as destination, dst, or target.

You can find out more key-value pair for the mount tag on the docker docs. But as for now, we're just going to use this three key-value pair.

After running the image in a container, we can see that inside the container directory, we can find /app directory. Or, if we're running web service, we can make a request to the service first, before searching for the directory.

After that we can run this command to verify that the bind mounts was created successfully:

docker inspect devtest

We'll going to see that the mount type is bind, it will also show correct source and destination.

What we have to know is that the docker bind mounts is bi-directional. What this means is, it's like two-way data binding that we're seeing a lot in front-end framework. Whether we create or edit a file in our host computer or container, both of the data will also be changed.

This is pretty useful in some areas. Let's say that we're building a frontend with HTML, css, and javascript. If we bind the css file to the container. Then, if we change the css in our host computer, our container css will also be changed. It will give us a realtime update without re-run the container.

The file or directory does not need to exist on the Docker host already. It is created on-demand if it does not yet exist. Bind mounts are very performant, but they rely on the host machine’s filesystem having a specific directory structure available. If you are developing new Docker applications, consider using named volumes instead. You can’t use Docker CLI commands to directly manage bind mounts.