人人都会AI编程

26.4 容器本质:被隔离与限制的 Linux 进程

更新时间:2026-07-12

许多人习惯把容器理解为“轻量级虚拟机”,但在 Linux 上,容器从根本上说只是一个普通的进程——它是借助内核已有的两项基础能力(命名空间和控制组)为进程加上“围墙”和“天花板”而实现的。宿主机的同一个内核直接运行着所有容器进程,没有任何额外的模拟层或中间操作系统。

1. 命名空间(namespace):让进程只能看到自己的“世界”
Linux 命名空间负责为进程创建独立、隔离的资源视图。当创建一个新容器(比如用 docker run)时,底层的 clone() 系统调用会在创建新进程的同时,为它指定一系列命名空间标志。目前 Linux 提供了八种命名空间,最核心的几种是:

  • Mount(mnt):容器拥有独立的文件系统挂载点视图,正是这个命名空间使容器只能看到属于自己的根文件系统(rootfs),而看不到宿主机的 / 目录。
  • PID:容器内进程看到的 PID 编号从 1 开始,形成一棵独立的进程树,而不会看到宿主机上的其他进程。容器内的 PID 1 就是该容器的“init”进程。
  • Network(net):容器拥有独立的网络栈(网卡、IP 地址、路由表、防火墙规则等),从而让多个容器可以各自监听相同的端口而不会冲突。
  • UTS:允许容器拥有自己的主机名和域名。
  • IPC:隔离进程间通信资源(如信号量、消息队列、共享内存)。
  • User:容器内可以使用与宿主机不同的用户/组 ID 映射,进一步提升安全性。
  • Cgroup:为容器提供独立的 cgroup 文件系统视图,避免容器感知到宿主机的资源限制层级。

可以用 lsns 命令查看系统中所有命名的空间,或通过 /proc/<PID>/ns/ 目录查看某个进程所处的命名空间标识。在宿主机上运行 ps aux,你可以看到容器内的 Web 服务进程——它和任何普通进程长一模一样,只是在不同的命名空间里“坐井观天”。

2. 控制组(cgroup):给进程加上资源使用的天花板
如果命名空间解决的是“看得到什么”的问题,控制组则解决“能用多少”的问题。cgroup 通过伪文件系统(/sys/fs/cgroup/)将进程分组,并对每组实施 CPU、内存、磁盘 I/O、网络等资源的限制或权重分配。

例如,启动一个容器时指定 --memory=256m,底层操作大致是:

  • /sys/fs/cgroup/memory/ 下创建或使用一个子目录(比如 docker/<容器ID>);
  • 将容器内的进程 PID 写入该目录的 cgroup.procs 文件;
  • memory.limit_in_bytes 文件写入 268435456(256MB 的字节值)。

内核会立即施加这些限制:如果容器内的进程试图使用超过 256MB 的物理内存,内核的 OOM Killer 就会介入,杀掉越界的进程。同理,CPU 权重、块设备 IOPS 限制、网络优先级等都可以通过修改对应 cgroup 子系统的参数文件来动态调整,无需重启容器。

3. 容器 = 命名空间 + cgroup + rootfs
从实现的角度来看,容器就是被一组命名空间隔离、受一组 cgroup 限制的普通进程,再配上一个独立挂载的文件树。你可以不用 Docker,直接用系统工具手动创建一个“手工容器”:

# 创建新的命名空间并指定根文件系统
unshare --mount --uts --ipc --pid --fork --mount-proc \
        chroot /path/to/rootfs /bin/bash

这行命令启动的 Bash 进程就运行在隔离的 UTS、IPC、挂载和 PID 命名空间中,并使用指定的根文件系统,本质上已经相当接近一个容器的雏形。在此基础上,再通过写 cgroup 文件限制其内存和 CPU,就得到了一个完整的“容器”。

4. 这一事实引发的实用结论

  • 容器不等于虚拟机:没有完整的操作系统内核在容器内启动,所以容器的启动时间接近进程启动时间(毫秒级),镜像中也不需要安装独立内核和固件。
  • 进程在宿主机上直接可见pstoppidstat 等工具都能看到容器进程,只不过需要留意 PID 在不同命名空间中的映射。调试时可以直接用宿主机的 stracegdb 附加到容器进程上,而不必进入容器内部。
  • 安全边界不等于虚拟机:容器共享宿主机内核,因此内核漏洞可能被容器突破。加固容器安全更多依赖正确配置的命名空间、cgroup、seccomp、SELinux/AppArmor,以及避免使用特权模式。
  • 资源限制是刚性的(除了 CPU 软限制):超出内存限制会直接触发 OOM,不可能像虚拟机那样“用到别的虚机未用的内存”。

总而言之,容器的本质就是 Linux 的进程隔离和资源限制机制经过巧妙组合后的高级抽象。理解这一点后,排查容器故障、优化资源配额或评估安全风险时,就不必再从黑盒的角度猜测,而是可以直接用 Linux 基本功(检查 /proc、cgroup、命名空间)去分析和控制。