我在 /mnt/container/ 下有 alpine 迷你根文件系统
我对挂载如何与 chroot 和 unshare 一起工作有点困惑。
如果我们取消分享,则无需取消分享
chroot /mnt/container /bin/sh -l
我们在主机上得到一个带有“/”(根)的容器(某种)/mnt/container
。
如果我们运行以下命令,则在容器内;
mount -t proc proc /proc >& /dev/null
mount -t devtmpfs dev /dev/ >& /dev/null
我们看到我们已经挂载了主机系统的 /proc 和 /dev,因此我们可以看到主机上正在运行的进程,ps -ef
并且也可以在 /dev 中创建一个文件,该文件将在主机上创建。这是预期的,因为仍然没有命名空间隔离。
为了创建命名空间隔离,我们这样做;
unshare -mpfu chroot /mnt/container /bin/sh -l
然后在容器内运行
mount -t proc proc /proc >& /dev/null
mount -t devtmpfs dev /dev/ >& /dev/null
这次ps -ef
将只显示容器内的两个进程。我的理解(如果我错了,请纠正我)是mount -t proc proc /proc >& /dev/null
没有挂载主机系统的 /proc,而是创建了一个 procfs 类型的新目录 /proc,因此隔离。
但是,这就是问题所在,容器内的 /dev 仍然与主机的 /dev 相同。我仍然可以在 /dev 中创建文件,它会显示在主机上。
为什么/dev不像/proc那样被隔离?
答案1
devtmpfs
没有命名空间(参见基于它的shmem
上下文初始化),并且它也不适合在用户命名空间内使用(请参阅devtmpfs 对于命名空间来说有什么特殊之处吗?权限问题)。
人们曾尝试改变这一点,例如Seth Forshee 提交的 2014 年补丁系列。但内核维护者,特别是 Greg KH,认为devtmpfs
在主机和用户命名空间之间共享一个实例,甚至是一个命名空间感知的实例,没有用:
将命名空间 devtmpfs 从 Loopdevfs 讨论中分离出来可能是明智的。然而,为了捍卫命名空间的 devtmpfs,我想说,对于用户空间来说,在每次容器启动时,将设备中的全局 devtmpfs 绑定挂载到私有 tmpfs(出于 systemd 的考虑,它不能仅仅位于容器 rootfs 上) ,似乎值得避免。
我认为必须在容器中选择您想要的设备节点是一件好事。事实上,无论如何,你都必须在内核中做同样的事情,用户空间在这里做出决定有什么问题,特别是因为它比内核更清楚地知道自己想要做什么。
基本上,如果您需要/dev
在用户命名空间内,则应该手动填充它。
/proc 如何与 PID 命名空间交互?解释了该/proc
行为。
答案2
Kevin Boone 的容器技术并不等同于 Docker 或虚拟机可能实现的容器化技术。
在 Linux 上,/dev 和 /proc 不是文件系统目录。它们是操作系统的特殊实体,恰好可以作为文件系统(如对象)访问。
许多命令需要检查这些实体的内容。
名为“dev”和“proc”的目录可以在任何地方创建,但它们可能看起来只是真正的 /dev 和 /proc 伪文件系统目录的“overalys”。