容器内的安装绑定未反映容器外部

容器内的安装绑定未反映容器外部

我正在尝试将主机目录绑定到容器内的某个目录,并期望容器内部所做的更改能够反映在主机上。

以下是我遵循的步骤

在主机上创建 /hostdir 并以特权模式运行 ubuntu 容器

[root@nhbdlin03 ~]# mkdir /hostdir
[root@nhbdlin03 ~]# docker run -itd --privileged --name ubuntu -v /hostdir:/hostdir:z ubuntu
76aebded33274e95a6f569d0831aee4df27e9f200a8fd0401448239bd6f5bf80
[root@nhbdlin03 ~]# docker exec -it ubuntu bash

在容器内创建container_dir

root@76aebded3327:/# mkdir /container_dir

绑定两个目录(成功)

root@76aebded3327:/# mount --bind /container_dir /hostdir

在 /container_dir 中创建一个名为 hello.txt 的文件

root@76aebded3327:/# cd container_dir/
root@76aebded3327:/container_dir# touch hello.txt

它在 /hostdir 内得到反映,因为它被绑定挂载到 /container_dir

root@76aebded3327:/container_dir# ls /hostdir/
hello.txt

退出容器并检查主机,是否反映相同

root@76aebded3327:/container_dir# exit

[root@nhbdlin03 ~]# ls /hostdir/
[root@nhbdlin03 ~]# ls /hostdir/ | wc -l
0
[root@nhbdlin03 ~]#

内容没有反映出来。
我遗漏了某些内容或做错了,请帮助我找到正确的方向。

答案1

这是设计使然——由于多种原因,在容器内部完成的安装从外部是看不见的。

容器运行在单独的挂载命名空间中(而不仅仅是简单的chroot),Docker 很有可能将新的命名空间配置为“私有”模式,一方面是为了防止容器的各种挂载扰乱主机的命名空间findmnt,另一方面是为了在容器退出时更容易地拆除所有挂载。

(当所有挂载只能从命名空间内部看到时,就足以终止所有进程 - 然后挂载将被内核自动拆除。但如果其中一些挂载在外部可见,则“主机操作系统”进程可能会将它们保持“正在使用”状态。)

您可能需要mount --make-[r]shared /在正确的时间让内部安装可见。我现在没有更准确的答案。

您可以使用unsharensenter工具来试验命名空间而不涉及 Docker - 例如unshare --mount --propagation=private在一个终端中运行,挂载某些东西,然后运行findmnt以查看它在“取消共享”过程的“内部”和“外部”报告不同的结果。

答案2

shared对我有用的是按照以下说明进行 Docker 绑定安装这个答案对于类似的问题“如何向主机公开容器的挂载点?”:

-v /hostdir:/hostdir:shared

根据Docker 的文档假设你的主机操作系统使用 SELinux,该z选项应该可以实现类似的功能,但我没有尝试过。

相关内容