如何在不重写现有文件的情况下重新装载docker卷?

运行Docker时,可以使用--volume选项来挂载文件和目录。 例如:

 docker run --volume /remote ./local myimage 

我正在运行一个在Dockerfile中定义VOLUMES的docker镜像。 我需要访问恰好在一个定义的卷内的configuration文件。 我想让这个文件在主机上“同步”,以便我可以编辑它。 我知道我可以运行docker exec ... ,但是我希望能绕过只编辑一个文件的开销。 我发现由VOLUMES行创build的卷存储在/var/lib/docker/volumes/<HASH>/_data

使用docker inspect我能够find挂载的目录:

 docker inspect gitlab-runner | grep -B 1 '"Destination": "/etc/gitlab-runner"' | head -n 1 | cut -d '"' -f 4 

输出:

在/ var / lib中/泊坞窗/卷/ 9c233c085c36380c6c33035222c16e5d061368c5060cc81dda2a9a713a2b2b3b / _data


所以问题是:

有没有办法重新安装在图像中定义的卷? 或者以某种方式获得目录比我上面的oneliner更容易?


编辑评论后齐柏林我已经尝试重新绑定音量没有成功:

 $ mkdir etc $ docker run -d --name test1 gitlab/gitlab-runner $ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner $ docker exec test1 ls /etc/gitlab-runner/ certs config.toml $ docker exec test2 ls /etc/gitlab-runner/ # empty. no files $ ls etc # also empty 

docker inspect正确地显示卷被绑定到~/etc ,但在/etc/gitlab-runner/容器内的文件似乎丢失。

 $ docker run -d --name test1 gitlab/gitlab-runner $ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner 

你有两种不同的卷types。 其中一个我称之为匿名卷(在运行docker volume ls时,可以看到很长的uuid)。 第二个是主机卷或绑定挂载,将主机上的目录直接映射到容器中。 所以你纺出来的每个容器都在看不同的地方。

匿名卷和命名卷( docker run -d -v mydata:/etc/gitlab-runner gitlab/gitlab-runner )被初始化为该目录位置的映像内容。 这个初始化只发生在卷是空的时候,并被挂载到一个新的容器中。 正如您所看到的,主机卷只能获取主机文件系统的内容,即使在该位置是空的。

在这样的背景下,对你的问题的简短回答是否定的,你不能将容器内的文件装载回主机。 但是,您可以使用多种方法将文件复制出来,前提是您不要使用主机卷装载覆盖文件的来源。 使用正在运行的容器,有docker cp命令。 我个人喜欢:

 docker run --rm -v ~/etc:/target gitlab/gitlab-runner \ cp -av /etc/gitlab-runner/. /target/. 

如果您有一个要复制或复制数据的命名卷,则可以使用任何映像以及执行该复制所需的工具:

 docker run --rm -v mydata:/source -v ~/etc:/target busybox \ cp -av /source/. /target/. 

尽量避免直接从主机修改容器内的数据,更好的方法是将任务包装到另一个容器中,然后以“–volumes-from”选项开始。

不知道我理解你的问题,无论如何,至于你提到的文件,

VOLUME指令创build一个具有指定名称的挂载点,并将其标记为从本地主机或其他容器中持有外部安装的卷。 […] docker run命令使用基础映像中指定位置上存在的任何数据初始化新创build的卷。

所以,下面的示例Dockerfile后,已经build立了图像

 docker build -t mytest . 

并让容器运行

 docker run -d -ti --name mytestcontainer mytest /bin/bash 

你可以从容器本身访问它,例如

 docker exec -ti mytestcontainer ls -l /myvol/greeting docker exec -ti mytestcontainer cat /myvol/greeting 

希望能帮助到你。