使用unshare创建隔离挂载命名空间的Linux容器问题咨询
嘿,这个坑我之前踩过!咱们先搞清楚问题出在哪,再一步步解决:
问题的核心:挂载命名空间的默认行为
你用 unshare -m 确实创建了一个新的挂载命名空间,但这里有个关键误区:新命名空间初始是完全复制主机的挂载树,而不是凭空生成一个空的隔离文件系统。
这意味着你在容器里的bash看到的文件系统和主机几乎一模一样——只是后续你在容器里执行的挂载/卸载操作不会同步到主机而已,但对原有文件系统的读写(比如创建/删除文件)依然会直接作用到主机的磁盘上,因为这些文件本身就存储在主机的文件系统里,挂载命名空间并没有隔离它们的访问权限。
实现完全文件系统隔离的正确步骤
要让容器的文件系统和主机彻底隔离,你需要在新挂载命名空间里切换根文件系统(也就是所谓的"rootfs")。下面是一套简单可行的操作流程:
1. 先准备一个基础的根文件系统
最简单的方式是用静态编译的busybox来搭建一个极简rootfs:
# 下载静态编译的busybox(无需依赖,直接运行) wget https://busybox.net/downloads/binaries/1.36.0-x86_64-linux-musl/busybox -O /tmp/busybox chmod +x /tmp/busybox # 创建容器根目录的基础结构 mkdir -p /tmp/container_root/{bin,sbin,etc,proc,sys,dev,home,root} # 复制busybox到容器根,并创建常用命令的软链接 cp /tmp/busybox /tmp/container_root/bin/ cd /tmp/container_root/bin for cmd in $(/tmp/busybox --list); do ln -s busybox $cmd; done
2. 启动隔离容器并切换根
执行以下命令进入完全隔离的环境:
# 创建新的挂载、PID命名空间(--pid确保容器有自己的PID 1),并启动bash unshare -m --fork --pid /bin/bash # 进入新命名空间后,先把根挂载设为私有,防止后续操作影响主机 mount --make-rprivate / # 切换到我们准备好的rootfs pivot_root /tmp/container_root /tmp/container_root/oldroot # 卸载旧的主机根目录(-l是懒卸载,避免占用) umount -l /oldroot # 挂载容器需要的虚拟文件系统 mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t devtmpfs devtmpfs /dev # 现在你可以执行bash进入隔离环境了 bash
现在你在这个bash里创建/删除文件,只会作用于容器的rootfs,完全不会影响主机的文件系统。
额外提醒
如果你只是临时测试,也可以直接挂载tmpfs作为容器的根(不需要提前准备busybox),这样所有文件都在内存里,退出后自动消失:
unshare -m --fork --pid /bin/bash mount --make-rprivate / mkdir -p /tmp/container_root mount -t tmpfs tmpfs /tmp/container_root pivot_root /tmp/container_root /tmp/container_root/oldroot umount -l /oldroot mount -t proc proc /proc bash
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

