dockerdocker-composemountdocker-volume

Can a Docker volume also be a bind mount?


In Docker documentation, there is a very clear distinction between a bind mount and a volume.

Yet, I stumbled upon this in a compose file, in the root-level volumes element.

volumes:
  myvolume:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: '/my/host/folder'    

I am pretty sure this is a volume, because it is visible in docker volume ls.

But the bind option suggests that this is also a bind mount.

Is my assumption correct? I.e. this is a kind of bind mount that binds to a docker volume rather than a container's internal folder (so, as a matter of fact, there are two "bindings" in place)?

How does this work from an operative system standpoint?

Does this still leverage the benefits of using a Docker volume?


Solution

  • Ignoring Docker for a moment, on a Linux host you can run mount --bind /old/dir /new/dir to make two directories have the same underlying disk storage. This has the same properties as a Docker bind mount; if you write to /new/dir it's also visible in /old/dir, and if anything was in /new/dir before the mount it's hidden. I believe it's possible to also write this as mount -o bind ... (though this copy of mount(8) doesn't document it).

    For a named volume, Docker's default setup internally is to create a directory in /var/lib/docker/volumes and then bind-mount that into the container. But you can manually create a volume using mount options as well, with documented uses being to mount a physical disk as a Docker volume or to mount a remote network drive.

    This syntax you show combines these two options. You "manually create a volume using mount options", but those mount options actually set up a bind mount.

    This has a couple of minor advantages. Other parts of your Compose setup don't need to know the host path, only the Compose-local volume name. If you make a mistake and the host directory doesn't exist, you'll get an error rather than the directory being created.

    This also brings with Docker's confusing and non-standard behavior about copying contents into new volumes: if the directory is empty, but only then, and only for Docker named volumes and not any other kind of mount, image content will be copied in. docker volume rm won't actually delete the host-directory content, only the mount point inside the Docker private filesystem space.

    For almost all uses I'd go with the inline-path syntax, in a specific container volumes: ['./dir:/container/path']. Since Compose can translate relative paths you can use ./dir to use a directory within your project tree, which minimizes the portability concerns around hard-coding host directories.