What's the difference between "docker run -v ..." volume and Dockerfile VOLUME?
Asked Answered
G

6

156

I have successfully been able to share folders between a docker container with volumes using

docker run -v /host/path:/container/path ...

But my question is what the difference between this and using the VOLUME command in the Dockerfile

VOLUME /path

I am using an image that has a VOLUME command, and I'd like to know how to share it with my host. I have done it using the -v command above, but I didn't know if I needed both the -v and VOLUME.

Grassgreen answered 14/8, 2014 at 15:14 Comment(1)
Please update the title, you're not asking how to mount volumes on hostOverseas
I
169

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.

Irrigate answered 14/8, 2014 at 16:10 Comment(5)
What happens if I use -v on a directory that was already specified in VOLUME?Grassgreen
--volumes-from will mount your VOLUME over the top of anything you specify with -v. Interestingly, it looks like running the container in privileged mode (docker run --privileged) and umounting /var/lib/mysql will just leave an empty dir so your -v mount is completely ignored when it conflicts with a VOLUME.Irrigate
You say volumes are kept as long as a container references them, and I've seen that elsewhere. docs.docker.com/userguide/dockervolumes says "Data volumes are designed to persist data, independent of the container's life cycle. Docker therefore never automatically delete volumes when you remove a container, nor will it "garbage collect" volumes that are no longer referenced by a container." One of these statements must be wrong.Disinfection
The files that are in the volume are kept on the disk when a container no longer references it, but the volume itself is no longer usable (unless you know exactly how to manually hook a volume up to a container, but even then I don't know if this is possible). When I say no longer usable, I mean you can't use --volumes-from to use it. When they say "garbage collect" above, they mean delete the files from your disk that were in the volume.Irrigate
They are usable using -v, but not --volumes-from. Volumes-from takes a container name to fetch volume data from (I believe it takes ALL volume points). For -v itself, however, the manual mentions that you can provide a named volume to -v in the form of named-volume:/path/in/container. Unnamed volumes are given hashes for names and those hashes can be provided instead of a host-path to access orphaned volumes. :) Be aware volume ls may not show them all - try docker volume ls -f dangling=true as well.Evidential
P
56

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
Perilune answered 1/4, 2015 at 11:28 Comment(3)
What if the docker host is running in a VM? For example, boot2docker on mac. Then these volumes are only available remotely. Also, when using volumes in the Dockerfile as you described, the contents of the image will be copied to the volume. However, when mounting to a local directory, this copying does not happen. Do you know why this is the case? Is there a way to have a locally mounted volume but still 'start fresh' with the files from the image?Millur
with docker-compose you can exactly do that, mount a volume on a specific location of the host os. No symlinks needed...Rickert
@Perilune : example docker-compose see the docs docs.docker.com/compose/compose-file/…Rickert
C
14

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>

Caines answered 26/9, 2016 at 7:36 Comment(0)
O
9

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

Oller answered 14/8, 2014 at 16:16 Comment(0)
V
9

This is from the Docker documentation itself, might be of help, simple and plain:

"The host directory is, by its nature, host-dependent. For this reason, you can’t mount a host directory from Dockerfile, the VOLUME instruction does not support passing a host-dir, because built images should be portable. A host directory wouldn’t be available on all potential hosts.".

Verbal answered 11/4, 2017 at 5:45 Comment(0)
L
4

If you came here because you were looking for a simple way to browse any VOLUME:

  1. Find out the name of the volume with docker volume list
  2. Shut down all running containers to which this volume is attached to
  3. Run docker run -it --rm --mount source=[NAME OF VOLUME],target=/volume busybox
  4. A shell will open. cd /volume to enter the volume.
Loredo answered 22/10, 2020 at 11:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.