我需要连接到 docker 容器内主机的所有磁盘的安装点。挂载信息在文件中可用/proc/1/mounts
,但我无法在所有操作系统上访问该文件。
当我在 Ubuntu 上运行以下命令时,它工作正常。
docker run -it -v /proc/1/mounts:/tmp/mounts ubuntu:16.04
但在启用了 SELinux 的 CentOS 上,我无法挂载/proc/1/mounts
文件。就会permission denied
报错。
我也尝试过/etc/mtab
,但由于它是 的符号链接/proc/self/mounts
,因此内容将在 docker 容器内发生变化。
除了 之外,是否还有其他方法来获取主机的挂载信息/proc/1/mounts
,或者应该使用特定的 SELinux 标签?
我尝试使用docker run -it --privileged -v /proc/1/mounts:/tmp/mounts ubuntu:16.04
,但它仍然给出相同的错误。
答案1
我假设您并不严格要求 init 进程 (pid 1) 可见的安装并且 docker 守护进程可见的安装就足够了。通常,它们应该具有相同的挂载命名空间。
CentOS docker 软件包的答案
(使用 CentOS 存储库中的 docker 1.13.1)
我可以用 重现你的问题/proc/1/mounts
。但是,使用 docker 守护进程的挂载文件可以:
$ docker run -it -v /proc/$(pidof dockerd-current)/mounts:/tmp/mounts ubuntu:16.04
在docker容器中,/tmp/mounts
然后列出主机的挂载。
Docker 社区版的答案
(使用外部 docker-ce 18.09.5 包如此处所述)
除了上面解释的问题之外,该docker-ce
包还存在服务的 SE Linux 上下文问题containerd
:
# ps xZ | grep containerd
system_u:system_r:unconfined_service_t:s0 5695 ? Ssl 0:00 /usr/bin/containerd
...
我们希望containerd
用 typecontainer_runtime_t
而不是来标记unconfined_service_t
。为此,/usr/bin/containerd
必须更新标签(一般参考):
# ls -Z /usr/bin/dockerd-ce
-rwxr-xr-x. root root system_u:object_r:container_runtime_exec_t:s0 /usr/bin/dockerd-ce
# ls -Z /usr/bin/containerd
-rwxr-xr-x. root root system_u:object_r:bin_t:s0 /usr/bin/containerd
# semanage fcontext -a -t container_runtime_exec_t /usr/bin/containerd
# restorecon /usr/bin/containerd
# ls -Z /usr/bin/containerd
-rwxr-xr-x. root root system_u:object_r:container_runtime_exec_t:s0 /usr/bin/containerd
接下来,重新启动containerd
守护进程:
# systemctl daemon-reload
# systemctl restart containerd
# ps xZ | grep containerd
system_u:system_r:container_runtime_t:s0 6557 ? Ssl 0:00 /usr/bin/containerd
现在,可以使用与上面相同的技术来启动 docker 容器(使用dockerd
代替dockerd-current
):
$ docker run -it -v /proc/$(pidof dockerd)/mounts:/tmp/mounts ubuntu:16.04
背景资料
我在 CentOS Linux 版本 7.6.1810 上对此进行了测试。
您可以验证 init 和 docker 守护进程是否具有相同的挂载命名空间(即它们的 /proc/[pid]/mounts 将显示相同的挂载):
# readlink /proc/1/ns/mnt /proc/$(pidof dockerd-current)/ns/mnt
mnt:[4026531840]
mnt:[4026531840]
我还验证了 SE Linux 已启用:
# getenforce
Enforcing
当使用 CentOS 软件包运行命令时,docker
我收到以下错误消息:
$ docker run -it -v /proc/1/mounts:/tmp/mounts ubuntu:16.04
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "container init exited prematurely".
此外,在 中/var/log/audit/audit.log
,我看到以下 AVC 违规:
type=AVC msg=audit(1555530383.707:214): avc: denied { mounton } for pid=5691 comm="runc:[2:INIT]" path="/var/lib/docker/overlay2/8944062749f8ad19c3ff600e1d5286315227378174b95a952e7b0530927f4dcd/merged/tmp/mounts" dev="proc" ino=45422 scontext=system_u:system_r:container_runtime_t:s0 tcontext=system_u:system_r:init_t:s0 tclass=file permissive=0
这告诉我们,SE Linux 规则不允许类型为“container_runtime_t”的源上下文对“init_t”类型的目标上下文执行“mounton”操作。您可以验证这是 的上下文/proc/1/mounts
,而 的上下文/proc/$(pidof dockerd-current)/mounts
匹配:
# ls -Z /proc/1/mounts /proc/$(pidof dockerd-current)/mounts
-r--r--r--. root root system_u:system_r:init_t:s0 /proc/1/mounts
-r--r--r--. root root system_u:system_r:container_runtime_t:s0 /proc/5476/mounts