What Is The Difference Between Binding Mounts And Volumes While Handling Persistent Data In Docker Containers?
Solution 1:
We basically have 3 types of volumes or mounts for persistent data:
Bind mounts
Named volumes
Volumes in dockerfiles
Bind mounts are basically just binding a certain directory or file from the host inside the container (docker run -v /hostdir:/containerdir IMAGE_NAME
)
Named volumes are volumes which you create manually with docker volume create VOLUME_NAME
. They are created in /var/lib/docker/volumes
and can be referenced to by only their name. Let's say you create a volume called "mysql_data", you can just reference to it like this docker run -v mysql_data:/containerdir IMAGE_NAME
.
And then there's volumes in dockerfiles, which are created by the VOLUME
instruction. These volumes are also created under /var/lib/docker/volumes
but don't have a certain name. Their "name" is just some kind of hash. The volume gets created when running the container and are handy to save persistent data, whether you start the container with -v
or not. The developer gets to say where the important data is and what should be persistent.
What should I use?
What you want to use comes mostly down to either preference or your management. If you want to keep everything in the "docker area" (/var/lib/docker
) you can use volumes. If you want to keep your own directory-structure, you can use binds.
Docker recommends the use of volumes over the use of binds, as volumes are created and managed by docker and binds have a lot more potential of failure (also due to layer 8 problems).
If you use binds and want to transfer your containers/applications on another host, you have to rebuild your directory-structure, where as volumes are more uniform on every host.
Solution 2:
Volumes
are the preferred mechanism for persisting data generated by and used by Docker containers. While bind mounts
are dependent on the directory structure of the host machine, volumes
are completely managed by Docker. Volumes
are often a better choice than persisting data in a container’s writable layer, because a volume does not increase the size of the containers using it, and the volume’s contents exist outside the lifecycle of a given container. More on
Differences between -v
and --mount
behavior
Because the -v
and --volume
flags have been a part of Docker for a long time, their behavior cannot be changed. This means that there is one behavior that is different between -v
and --mount
.
If you use -v
or --volume
to bind-mount a file or directory that does not yet exist on the Docker host, -v
creates the endpoint for you. It is always created as a directory.
If you use --mount
to bind-mount a file or directory that does not yet exist on the Docker host, Docker does not automatically create it for you, but generates an error. More on
Docker for Windows shared folders limitation
Docker for Windows does make much of the VM transparent to the Windows host, but it is still a virtual machine. For instance, when using –v
with a mongo container, MongoDB needs something else supported by the file system. There is also this issue about volume mounts being extremely slow.
More on
Solution 3:
Bind mounts are like a superset of Volumes (named or unnamed). Bind mounts are created by binding an existing folder in the host system (host system is native linux machine or vm (in windows or mac)) to a path in the container.
Volume command results in a new folder, created in the host system under /var/lib/docker
Volumes are recommended because they are managed by docker engine (prune, rm, etc).
A good use case for bind mount is linking development folders to a path in the container. Any change in host folder will be reflected in the container. Another use case for bind mount is keeping the application log which is not crucial like a database.
Command syntax is almost the same for both cases:
bind mount: note that the host path should start with '/'. Use $(pwd) for convenience.
docker container run -v /host-path:/container-path image-name
unnamed volume: creates a folder in the host with an arbitrary name
docker container run -v /container-path image-name
named volume: should not start with '/' as this is reserved for bind mount. 'volume-name' is not a full path here. the command will cause a folder to be created with path "/var/lib/docker/volumes/volume-name" in the host.
docker container run -v volume-name/container-path image-name
A named volume can also be created beforehand a container is run (docker volume create). But this is almost never needed.