46

I'm new to Docker and am excited about using the --volumes-from feature but there's something I'm not understanding.

If I want to use --volumes-from with two data-only containers, each of which exports volumes named /srv, how to I prevent the volume paths from colliding? I can map volume names when creating a bind mount using [host-dir]:[container-dir]; how do I do that with --volumes-from?

So what I want would look something like this:

docker run --name=DATA1 --volume=/srv busybox true
docker run --name=DATA2 --volume=/srv busybox true
docker run -t -i -rm --volumes-from DATA1:/srv1 --volumes-from DATA2:/srv2 ubuntu bash
David Braun
  • 5,573
  • 3
  • 36
  • 42

2 Answers2

44

It can be done, but it is not supported at this moment in docker commandline interface.

How-to

Find the volumes directories:

docker inspect DATA1 | grep "vfs/dir"
# output something like:
# "/srv": "/var/lib/docker/vfs/dir/<long vol id>"

So, you can automate this, and mount these directories at mount points of your choice:

# load directories in variables:
SRV1=$(docker inspect DATA1 | grep "vfs/dir" | awk '/"(.*)"/ { gsub(/"/,"",$2); print $2 }')
SRV2=$(docker inspect DATA2 | grep "vfs/dir" | awk '/"(.*)"/ { gsub(/"/,"",$2); print $2 }')

now, mount these volumes by real directories instead of the --volumes-from:

docker run -t -i -v $SRV1:/srv1 -v $SRV2:/srv2 ubuntu bash

IMO, the functionality is identical, because this is the same thing that is done when using --volumes-from.

Jiri
  • 16,425
  • 6
  • 52
  • 68
  • 3
    **Note:** If you bind volumes from DATA1 like this, the volumes will be deleted on `docker rm -v DATA1` or `docker volume prune` when the DATA1 container has been removed. – Cani Aug 03 '17 at 12:54
  • 1
    Still not implemented? We are in 2018 :-) – jjmerelo Apr 16 '18 at 07:49
4

For completeness...

#create data containers
docker run --name=d1 -v /svr1 busybox sh -c 'touch /svr1/some_data'
docker run --name=d2 -v /svr2 busybox sh -c 'touch /svr2/some_data'

# all together...
docker run --rm --volumes-from=d1 --volumes-from=d2 busybox sh -c 'find -name some_data'
# prints:
#  ./svr2/some_data
#  ./svr1/some_data

# cleanup...
docker rm -f d1 d2

The "--volumes-from=container" just map over the filesystem, like mount --bind

If you want to change the path, Jiri's answer is (currently) the only way. But if you are in a limited environment you might want to use dockers built in inspect parsing capabilities:

# create data containers
docker run --name=DATA1 --volume=/srv busybox sh -c 'touch /srv/some_data-1'
docker run --name=DATA2 --volume=/srv busybox sh -c 'touch /srv/some_data-2'

# run with volumes and show the data
docker run \
  -v $(docker inspect -f '{{ index .Volumes "/srv" }}' DATA1):/srv1 \
  -v $(docker inspect -f '{{ index .Volumes "/srv" }}' DATA2):/srv2 \
  --rm busybox sh -c 'find -name some_data-*'
# prints:
# ./srv2/some_data-2
# ./srv1/some_data-1

# ditch data containers...
docker rm -f DATA1 DATA2

this probably even works with the old bash version that comes with boot2docker.

Florian F
  • 4,044
  • 3
  • 30
  • 31
  • Note: with docker .1.8, .Volumes "/srv" would be empty: see http://stackoverflow.com/a/31997267/6309 – VonC Aug 13 '15 at 20:14
  • Since the "Mount" now also has a "Driver" entry it seems like volume drivers are getting implemented after all... So it's probably not safe to assume that volumes will be accessible via the local file system for long. So don't change the path in the second step, map it where you want to have it in the first step. That is pretty much the Docker way of doing things... you don't change running containers, you throw it away and start a new one. – Florian F Aug 14 '15 at 22:30