docker - volumes vs mount binds. what are the use cases?

After reading and playing around with docker for a short while, I am considering using it in my production environment. However I am still trying to understand the difference between mount binds and volumes.

According to Dockers documentation on mount binds (https://docs.docker.com/storage/bind-mounts/):

Bind mounts have been around since the early days of Docker. Bind mounts have limited functionality compared to volumes. When you use a bind mount, a file or directory on the host machine is mounted into a container. The file or directory is referenced by its full or relative path on the host machine. By contrast, when you use a volume, a new directory is created within Docker’s storage directory on the host machine, and Docker manages that directory’s contents.

From this (and from playing around) it appears to me that mount binds and volumes are the same thing, the only difference being the location of the data. (volumes stored in docker's "private" storage area, while mount binds can be stored anywhere). Yes, mount bind have to exist prior to starting the docker container, while volumes can be created by the docker engine when the container starts- but this difference is irreverent performance or maintenance wise.

I wasn't able to understand the supposedly benefits of volumes stated by the documentation (https://docs.docker.com/storage/volumes/) as all of them seem to apply to mount binds just the same.

Can anyone please explain the main differences between volumes and mount-binds (performance and maintenance wise) and most importantly their use cases?

thanks for the help.

By default, a local named volume is exactly as you describe, a bind mount to a special docker directory. The differences I see:

  • First, the big one is a behavior difference between named volumes and host volumes (aka bind mounts). Docker will initialize a named volume from the contents of the image. This includes the file owners and permissions. This means you can avoid worrying about permission issues that are commonly encountered with host volumes.

  • Second, portability. Named volumes can be used from different docker hosts without worrying about the local filesystem paths or the user running the commands. Whether it's on a MacOS laptop, or a Linux server in production, you can just name a volume and assume it will work as part of the default docker install.

  • Third, how they are managed. Host volumes are commonly managed outside of docker which is where the permission problems often come into play (since UID/GID on the host commonly doesn't match the UID/GID inside the container). With named volumes, you would manage them from within another docker container where you can control what tools are installed, users created, etc.

There's also another big difference with named volumes. That's because I said "by default" above, and a named volume can be configured in quite a few ways. The volume driver can be changed to another one that is cloud aware. Or you can pass options to the local volume driver to change from the local bind mount to a specific directory to anything you can do with the mount syscall. That includes performing a bind mount to a different directory, an NFS mount, and you could even create your own overlay filesystem as a volume to allow containers to access and modify some data inside of the container without changing the underlying files in a base layer.

By using named volumes, you can also separate the management of the storage from the management of the containers. You simply point to the name and an external tool could create that volume to point to the appropriate location in that environment.

A few examples of named volumes I've used with the local volume driver include:

# named bind mount
$ docker volume create --driver local \
      --opt type=none \
      --opt device=/home/user/test \
      --opt o=bind \
      test_vol

# nfs
$ docker volume create --driver local \
      --opt type=nfs \
      --opt o=nfsvers=4,addr=nfs.example.com,rw \
      --opt device=:/path/to/dir \
      foo

# overlay
$ docker volume create --driver local --opt type=overlay \
    --opt o=lowerdir=${PWD}/ro-data,upperdir=${PWD}/upper1,workdir=${PWD}/work1 \
    --opt device=overlay overlay1