如何使用Docker的--volumes-from映射卷路径?

46
我是 Docker 的新手,并且对使用 --volumes-from 功能感到兴奋,但有些东西我不太明白。如果我想要在两个数据容器中使用 --volumes-from,每个容器都导出了名称为 /srv 的卷,我该如何避免卷路径冲突呢?当创建绑定挂载时,我可以通过使用 [host-dir]:[container-dir] 来映射卷名称;但是在使用 --volumes-from 时该怎么做呢?因此,我想要的效果应该类似于这样:
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

1
这个问题在 GitHub 上有相应的 issue 吗?这会非常有用。 - Anentropic
@Anentropic 我还没有创建一个。 - David Braun
看起来@Anentropic创建了这个问题https://github.com/docker/docker/issues/11261,但它已经被吸收到其他与卷相关的工作中。 - Jason Stangroome
2个回答

44

可以做到,但目前在Docker命令行界面中不支持。

操作步骤

查找卷目录:

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

因此,您可以自动化此过程,并将这些目录挂载到您选择的挂载点:

# 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 }')

现在,通过实际目录而不是 --volumes-from 来挂载这些卷:

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

我的看法是,这个功能是相同的,因为使用 --volumes-from 时也是这样做的。


3
注意:如果您像这样绑定 DATA1 的卷,则在删除 DATA1 容器后运行“docker rm -v DATA1”或“docker volume prune”时,这些卷将被删除。 - Cani
1
还没有实现吗?我们已经到2018年了 :-) - jjmerelo

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

"--volumes-from=container" 只是像 mount --bind 一样映射文件系统。
如果你想要改变路径,Jiri的回答(目前)是唯一的方法。 但是如果你处于一个受限制的环境中,你可能想要使用docker内置的检查解析功能。"
# 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

这可能甚至适用于boot2docker附带的旧版bash。

注意:使用Docker 1.8版本时,.Volumes "/srv"将为空,请参见https://dev59.com/Cl0a5IYBdhLWcg3wmZzC#31997267。 - VonC
由于“Mount”现在也有了“Driver”条目,看起来卷驱动程序终究会得到实现... 因此,很可能不能安全地假定卷将通过本地文件系统长期访问。 因此,在第二步中不要更改路径,在第一步中映射它到您想要的位置。这基本上是Docker的工作方式... 您不更改正在运行的容器,而是丢弃它并启动一个新容器。 - Florian Fida

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接