我需要在 Docker 容器中创建命名空间。作为其中的一部分,我需要将/proc
私有挂载到内部命名空间。我意识到我必须以某些特权运行容器才能实现这一点,但我更愿意启用最小的集合。
这有效:
$ sudo docker run --privileged --security-opt=seccomp=unconfined \
-it fedora:rawhide /usr/bin/unshare -Ufmp -r \
/bin/sh -c 'mount -t proc proc /proc'
这不会:
$ sudo docker run --cap-add=sys_admin --security-opt=seccomp=unconfined \
-it fedora:rawhide /usr/bin/unshare -Ufmp -r \
/bin/sh -c 'mount -t proc proc /proc'
mount: /proc: cannot mount proc read-only.
因此,仅关闭 seccomp 过滤器并添加CAP_SYS_ADMIN
是不够的。什么是足够的?
更新: Selinux 是问题的一部分。如果你在全局范围内关闭 selinux 强制,它会起作用。但是,您也可以使用 关闭对特定容器的强制执行--security-opt label:disable
,这在在线 Docker 手册的安全配置部分中有记录:
sudo docker run --cap-add=sys_admin --security-opt label:disable \
-it fedora:rawhide /usr/bin/unshare -fmp /bin/sh -c \
'mount --make-private / ; mount -t proc proc /proc'
但是,如果将-U
和-r
标志添加回unshare
. 而且,当然,添加--privileged
到 docker run 命令即使使用-U
and-r
标志也可以正常工作。
我目前正在尝试使用内核跟踪的东西来弄清楚究竟是什么给了我一个 EPERM。这是一个非常无用的非特定错误。
此命令有效:
我没有将它分成多行,因为引用非常重要。
/proc
基本上,它在运行 unshare 并/proc
在子用户命名空间中挂载之前卸载了一大堆东西。Docker 挂载了一堆目录和文件,
/proc
其中包含自己的目录,这些目录是空的 tmpfs 目录和空文件。中的各种文件/proc
表示适用于整个系统的值。事实上,/proc/kcore
如果你是 root,就可以读取容器内的内核内存,因为很多人想相信容器是某种轻量级 VM 之类的东西,这会让很多人感到惊讶。内核(从版本 4.14 开始)
fs/namespace.c:mnt_already_visible
检查您是否正在挂载一个已经挂载的文件系统,如果该文件系统有作为子文件系统挂载的东西并且这些挂载具有 MNT_LOCKED 标志,它会失败。每当您创建用户命名空间时,似乎都会将 MNT_LOCKED 标志应用于所有挂载(我没有追查内核中的位置),以防止您卸载该命名空间中的东西(因为您在“内部”获得特权用户命名空间)并使隐藏的东西再次可见。我发布的命令使用 awk 脚本来提取Docker 已挂载
/proc/1/mountinfo
的所有子目录和文件,然后将它们全部卸载。/proc
这使得/proc
文件系统可以再次安装在嵌套的用户命名空间中。