我正在尝试将主机目录绑定到容器内的某个目录,并期望容器内部所做的更改能够反映在主机上。
以下是我遵循的步骤
在主机上创建 /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 /
在正确的时间让内部安装可见。我现在没有更准确的答案。
您可以使用unshare
和nsenter
工具来试验命名空间而不涉及 Docker - 例如unshare --mount --propagation=private
在一个终端中运行,挂载某些东西,然后运行findmnt
以查看它在“取消共享”过程的“内部”和“外部”报告不同的结果。
答案2
shared
对我有用的是按照以下说明进行 Docker 绑定安装这个答案对于类似的问题“如何向主机公开容器的挂载点?”:
-v /hostdir:/hostdir:shared
根据Docker 的文档假设你的主机操作系统使用 SELinux,该z
选项应该可以实现类似的功能,但我没有尝试过。