docker mounting volumes on host

The VOLUME command will mount a directory inside your container and store any files created or edited inside that directory on your hosts disk outside the container file structure, bypassing the union file system.

The idea is that your volumes can be shared between your docker containers and they will stay around as long as there's a container (running or stopped) that references them.

You can have other containers mount existing volumes (effectively sharing them between containers) by using the --volumes-from command when you run a container.

The fundamental difference between VOLUME and -v is this: -v will mount existing files from your operating system inside your docker container and VOLUME will create a new, empty volume on your host and mount it inside your container.

Example:

  1. You have a Dockerfile that defines a VOLUME /var/lib/mysql.
  2. You build the docker image and tag it some-volume
  3. You run the container

And then,

  1. You have another docker image that you want to use this volume
  2. You run the docker container with the following: docker run --volumes-from some-volume docker-image-name:tag
  3. Now you have a docker container running that will have the volume from some-volume mounted in /var/lib/mysql

Note: Using --volumes-from will mount the volume over whatever exists in the location of the volume. I.e., if you had stuff in /var/lib/mysql, it will be replaced with the contents of the volume.


Basically VOLUME and -v option are almost equal. These mean 'mount specific directory on your container'. For example, VOLUME /data and -v /data is exactly same meaning. If you run the image that have VOLUME /data or with -v /data option, /data directory is mounted your container. This directory doesn't belong to your container.

Imagine that You add some files to /data on the container, then commit the container into new image. There isn't any files on data directory because mounted /data directory is belong to original container.

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

This mounted directory like /data is used to store data that is not belong to your application. And you can predefine the data directory that is not belong to the container by using VOLUME.

A difference between Volume and -v option is that you can use -v option dynamically on starting container. It mean you can mount some directory dynamically. And another difference is that you can mount your host directory on your container by using -v


VOLUME is used in Dockerfile to expose the volume to be used by other containers. Example, create Dockerfile as:

FROM ubuntu:14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

build the image:

$ docker build -t testing_volume .

Run the container, say container1:

$ docker run -it <image-id of above image> bash

Now run another container with volumes-from option as (say-container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

You will get all data from container1 /myvol directory into container2 at same location.

-v option is given at run time of container which is used to mount container's directory on host. It is simple to use, just provide -v option with argument as <host-path>:<container-path>. The whole command may be as $ docker run -v <host-path>:<container-path> <image-id>


Let me add my own answer, because I believe the others are missing the point of Docker.

Using VOLUME in the Dockerfile is the Right Way™, because you let Docker know that a certain directory contains permanent data. Docker will create a volume for that data and never delete it, even if you remove all the containers that use it.

It also bypasses the union file system, so that the volume is in fact an actual directory that gets mounted (read-write or readonly) in the right place in all the containers that share it.

Now, in order to access that data from the host, you only need to inspect your container:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

What I usually do is make symlinks in some standard place such as /srv, so that I can easily access the volumes and manage the data they contain (only for the volumes you care about):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log