手搓 Linux 容器隔离:原来 Docker 的黑科技,两行命令就能实现
1. 开篇:先拆穿 Docker 的 “马甲”
1.1 一个扎心真相:隔离根本不是 Docker 发明的
很多刚接触容器的同学都会感叹:Docker 也太神了!居然能把程序关进小盒子里,互不干扰,跟开了台虚拟机似的。
我当初也是这么想的,直到亲手玩了一遍 Linux 原生的 Namespace 机制 —— 好家伙,隔离能力根本不是 Docker 发明的,Linux 内核二十年前就把工具做好了。Docker 本质就是个 “装修包工头”,把内核自带的隔断墙拼一拼,精装修成了拎包入住的 “容器套房”。
今天咱们用最通俗的比方、最保姆级的步骤,带你亲手搓出两种最核心的隔离:PID 进程隔离和 Mount 文件隔离。全程命令都标清了操作窗口,跟着敲一遍,你就能拍着胸脯说:容器隔离?也就那么回事儿。
1.2 统一世界观:Linux 就是一栋打工人大楼
在正式动手之前,咱们把所有专业术语全部翻译成 “上班梗”,记住这组类比,后面所有内容你都能秒懂:
1.2.1 PID = 员工工号
- 每个运行的程序(进程)都是大楼里的打工人,人人有唯一工号,也就是 PID
- 工号 1 是大楼老板(init/systemd 进程),所有员工都是他的下属
- 正常情况下全楼共用一套工号,抬头不见低头见
1.2.2 Mount = 储物箱的摆放位置
- 磁盘、U 盘、镜像文件 = 一个个储物箱
- 挂载(mount)= 把储物箱放到某个房间门口,打开门就能拿里面的东西
- 全楼默认共用一张 “储物箱摆放清单”,哪儿放了硬盘、哪儿插了 U 盘,所有人都能看到
1.2.3 Namespace = 独立办公室隔断墙
- 这是 Linux 内核自带的 “装修技能”:可以在大楼里随便围出独立办公室
- 每个办公室有自己独立的规则:自己的工号表、自己的储物清单、甚至自己的主机名
- 办公室里的人以为自己在整栋楼里,其实根本看不到外面的世界
- Docker 容器,就是用 6 种不同的 Namespace 围出来的 “全能独立办公室”
2. 实战一:PID 进程隔离 —— 给自己开一间 “摸鱼独立办公室”
2.1 先搞懂:PID 隔离到底隔了个啥
通俗说就是:给你单独围一间办公室,里面重新排工号,你进去就是 1 号员工(办公室老板),外面的人你一个都看不见,专心摸鱼没人管。
外面的大楼其实能看到你,但显示的是大楼统一的工号;你在里面用自己的小工号,两边互不干扰。
2.2 保姆级实操(单窗口操作,全程跟着敲就行)
全程只用一个终端窗口,我们会先在宿主机环境查看状态,再进入隔离空间验证,最后退回来。
2.2.1 第一步:先看看大楼的全员花名册
【操作窗口:初始终端(宿主机原生环境)】 先看看正常情况下,系统里有多少进程:
ps -ef
你会看到乌泱泱一大片进程,PID=1 的是系统老大,各种服务、程序排得满满当当。这就是整栋大楼的员工总名册。
2.2.2 第二步:一键搬进独立办公室
【操作窗口:同一个初始终端(宿主机环境执行)】 敲下面这行魔法命令,瞬间开启 PID 隔离:
sudo unshare --fork --pid --mount-proc /bin/bash
回车之后看起来界面没什么变化,但你已经成功搬进新办公室了 —— 当前终端已经进入了全新的 PID 隔离空间。
2.2.3 第三步:验收!你现在就是办公室的 1 号员工
【操作窗口:当前终端(已进入 PID 隔离空间)】 再敲一次查看进程的命令:
ps -ef
见证奇迹的时刻到了:
- 进程只剩 2 个:一个 bash(就是你当前的命令行程序),一个刚执行的 ps 命令
- bash 的 PID 居然是 1!你就是这个小空间里的 “老板”
- 外面宿主机上的几百个进程,一个都看不见了
恭喜你,已经亲手实现了 Docker 最核心的能力之一:进程隔离。
2.2.4 第四步:退出隔离,回到大楼
【操作窗口:当前终端(隔离空间内)】 玩够了输入下面的命令,就能回到原来的宿主机环境:
exit
退出之后再执行 ps -ef,又能看到满屏的进程了,一切恢复原样。
2.3 扒一扒每个参数的真实作用
很多同学抄命令能跑,但每个参数干啥的一头雾水,咱们挨个唠明白:
2.3.1 --fork:为啥不能本人直接进办公室?
打个比方:你现在人在大楼大厅,总不能把大厅直接搬进办公室吧?
--fork 就是新建一个分身进程,让这个分身进到新的 PID 空间里。你原来的终端进程还在大楼里,操控着里面的分身。不加这个参数会直接报错,相当于 “穿墙失败”。
2.3.2 --mount-proc:为啥 ps 命令要单独配花名册?
这是初学者最容易踩的坑:ps 命令根本不是 “主动数进程” 的,它是去 /proc 目录里读 “员工花名册” 的。
你虽然人进了新办公室,但如果花名册还是大楼那本,ps 一查还是全楼的人,等于白隔离。--mount-proc 就是给你的新办公室单独印一本花名册,只记录办公室里的员工,这样 ps 出来的结果才是对的。
3. 实战二:Mount 挂载隔离 —— 藏起你的私人小 U 盘
3.1 先搞懂:Mount 隔离到底隔了个啥
如果说 PID 隔离是 “看不见人”,那 Mount 隔离就是 “看不见储物箱”。
通俗说:给你一间办公室,里面有自己独立的储物清单。你在里面摆新箱子、藏私房钱,外面大楼完全看不见;外面摆了啥,你里面也可以选择看不到。
这就是容器里文件系统独立的底层原理 —— 每个容器都以为自己有一整套 /bin、/etc、/usr 目录,其实都是用 Mount 隔离单独挂上去的。
3.2 提前准备:开好两个终端窗口
本次实验需要两个终端窗口对照,提前开好并分清楚:
- 窗口 A:宿主机原生环境(相当于大楼大厅),只用来对照验证,不做修改操作
- 窗口 B:实验专用窗口,用来创建隔离环境、执行挂载操作
3.3 保姆级实操(每一步都标清窗口,绝对不迷路)
3.3.1 第一步:先看一眼宿主机的储物清单
【操作窗口:窗口 A(宿主机原生环境)】 先查看当前系统的磁盘挂载情况,心里有个 baseline:
df -h
这就是大楼当前所有储物箱的全景图:系统盘、临时内存盘、各种挂载点,一目了然。先记下来,一会儿对比用。
3.3.2 第二步:给窗口 B 开启 Mount 隔离
【操作窗口:窗口 B(初始是宿主机环境,执行命令后进入隔离空间)】 先执行隔离命令,开启独立的挂载空间:
sudo unshare --mount --fork /bin/bash
执行完之后,窗口 B 看起来没变化,但实际上已经进入了全新的 Mount 隔离空间。接下来我们在这个窗口里做的所有挂载 / 卸载操作,都只会影响这个隔离空间,外面的窗口 A 完全不受影响。
顺手再建一个空文件夹,一会儿当 “U 盘插口” 用:
mkdir -p /data/tmpmount
3.3.3 第三步:手工造一个 80M 的迷你 U 盘
【操作窗口:窗口 B(Mount 隔离空间内)】 我们用 dd 命令凭空生成一个镜像文件,相当于手工做了一个空 U 盘:
dd if=/dev/zero of=fdimage.img bs=8k count=10240
大白话翻译:
if=/dev/zero:从 “无限空数据生成器” 里取原料of=fdimage.img:输出成一个叫 fdimage.img 的文件bs=8k count=10240:每次舀 8k,舀 10240 次,算下来正好 80M 左右
执行完你就得到了一个 80M 的 “空白 U 盘文件”。
3.3.4 第四步:给 U 盘格式化,不然装不了东西
【操作窗口:窗口 B(Mount 隔离空间内)】 空 U 盘不能直接存文件,得格式化一下,咱们格成 Linux 最常用的 ext4 格式:
mkfs -t ext4 ./fdimage.img
就跟你给新 U 盘选 “NTFS 格式”“FAT32 格式” 一个道理。中间提示 “这不是块特殊设备,还要继续吗”,输入 y 回车就行。
3.3.5 第五步:把 U 盘 “插” 到指定门口
【操作窗口:窗口 B(Mount 隔离空间内)】 现在把这个做好的镜像文件,挂载到我们刚才建的 /data/tmpmount 目录上:
mount ./fdimage.img /data/tmpmount
这一步就是真正的 “挂载”:把储物箱放到房间门口,以后打开这个文件夹,就是打开这个 U 盘。
3.3.6 第六步:往里塞个小秘密
【操作窗口:窗口 B(Mount 隔离空间内)】 我们往这个私人 U 盘里写个文件,一会儿验证隔离效果:
echo "这是我的小秘密,外面看不见" > /data/tmpmount/secret.txt
3.4 见证奇迹:两个窗口对比看隔离效果
3.4.1 隔离空间里:文件磁盘都正常
【操作窗口:窗口 B(隔离空间内)】 分别执行两条命令,确认我们的 U 盘和文件都在:
df -h
cat /data/tmpmount/secret.txt
你会清晰地看到我们刚挂载的 80M 磁盘,也能正常读出文件内容。一切都很合理。
3.4.2 宿主机上:啥也看不到
【操作窗口:窗口 A(宿主机原生环境)】 切回窗口 A,执行同样的命令:
df -h
ls /data/tmpmount
神奇的事情发生了:
df -h里完全找不到那个 80M 的磁盘/data/tmpmount目录里看不到secret.txt文件
文件明明就存在磁盘上,宿主机就是 “看不见、查不到”,这就是 Mount 命名空间的隔离魔力。
3.4.3 灵魂追问:窗口 A 里到底有没有 /data/tmpmount 这个文件夹?
这是 90% 的初学者都会懵的问题,这里给你说透: 窗口 A 里能看到 /data/tmpmount 这个文件夹本身,但文件夹是空的,看不到里面的文件,也看不到挂载的 80M 磁盘。
很多人会误以为 “隔离了就连目录都看不见”,其实不是。咱们这次实验只开启了「挂载表隔离」,并没有换掉整个根文件系统,底层的磁盘、目录结构两边其实共用同一块硬盘。 窗口 B 里执行 mkdir -p /data/tmpmount,是真真切切在磁盘上创建了这个目录,既然是写在磁盘上的真实文件,窗口 A 当然也能看到这个空文件夹。
那 Mount 隔离到底隔离了啥?隔离的是「挂载关系」,不是目录本身。 窗口 B 把镜像盘挂到了 /data/tmpmount 上,这条 “摆放记录” 只写在了窗口 B 自己的挂载清单里,窗口 A 的总清单里完全没有这条记录。所以:
- 窗口 B 打开这个目录:系统查自己的挂载表,发现这儿挂了个 U 盘,于是显示 U 盘里的内容
- 窗口 A 打开这个目录:系统查自己的挂载表,发现这儿啥也没挂,于是只显示磁盘上原本的空目录
用大楼类比就是:/data/tmpmount 是走廊里一块固定的空位,所有人都能看见这块地方;但你在这儿摆了个箱子这件事,只有你办公室的清单有记录,外面的人路过只看到空地,根本不知道这儿摆了箱子。
补充:如果想连目录本身都让外面彻底看不见,就得配合 Mount Namespace 做「换根目录」(pivot_root/chroot),直接把整个根文件系统都换掉。Docker 容器里看不到宿主机目录,用的就是这个技术。咱们这个基础实验只演示最核心的挂载隔离原理,没做换根。
3.4.4 收尾:退出隔离环境
【操作窗口:窗口 B(隔离空间内)】 实验做完,输入命令退出隔离空间:
exit
退出之后,所有临时挂载自动消失,宿主机干干净净,不留一丝痕迹。而 fdimage.img 这个文件还会保留在磁盘上,下次再挂载还能读到里面的内容。
3.5 课后小问答
3.5.1 退出隔离后,U 盘里的文件会消失吗?
不会。fdimage.img 这个镜像文件还好好躺在磁盘上,里面的 secret.txt 也还在。消失的只是 “挂载关系”,也就是 “储物箱的摆放记录”。你下次再挂载一次,文件还能完整读出来。
3.5.2 为啥文件真实存在,外面就是看不见?
因为 Mount 隔离隔的是「挂载表」,不是磁盘本身。就好比你把箱子放在了办公室门后,大厅的清单上没登记,别人自然不知道这个门口放了箱子,打开门当然是空的。箱子本身一直都在,只是外面的系统不知道它被摆在了那儿。
4. 收尾:原来 Docker 就是个 “装修包工头”
4.1 六种 Namespace 齐上阵,凑出一个完整容器
今天我们只玩了 PID 和 Mount 两种 Namespace,实际上 Linux 一共提供了 6 种隔断墙,Docker 全都用上了:
- PID Namespace:隔离进程工号
- Mount Namespace:隔离文件挂载
- UTS Namespace:隔离主机名(容器能自己起名字)
- IPC Namespace:隔离进程间通信
- Network Namespace:隔离网络(每个容器有自己的 IP、端口)
- User Namespace:隔离用户权限(容器里的 root 在外面就是普通用户)
Docker 干的事儿,就是把这 6 面墙一围,再给你铺好地板(镜像文件系统)、接好网线(网络桥接),最后告诉你:“拎包入住吧,这就是你的独立服务器”。
4.2 写给初学者的心里话
很多技术听起来高大上,剥开外壳都是朴素的底层原理。Namespace 不是什么黑科技,就是 Linux 内核给我们准备的一套积木。
今天你能用 unshare 手搓出隔离,明天再看 Docker、K8s 这些东西,就不会再觉得 “深不可测”—— 它们无非是把这些底层积木,搭成了更漂亮、更好用的房子而已。
技术的世界就是这样:看懂了本质,就只剩一层窗户纸.
更多推荐

所有评论(0)