容器本质是受多重内核机制约束的普通进程:namespace实现视图隔离(pid、network、mount等),cgroup限制资源使用(cpu、内存等),capabilities、seccomp和lsm进一步加固安全边界,docker仅是封装这些底层能力的运行时工具。

因为容器在操作系统层面确实就是一个进程,只是被内核施加了多项约束——它不启动新内核、不模拟硬件、也不运行独立操作系统,所有行为都依托于宿主机的 Linux 内核。
Namespace 实现视图隔离
Linux 的 namespace 机制让这个进程“看不见”其他进程和资源。比如 PID namespace 让容器内的主程序成为 PID 1,它看不到宿主机上成百上千的其他进程;Network namespace 让它拥有独立的网卡、IP 和端口空间;Mount namespace 则让它挂载一套专属的文件系统视图。这些不是虚拟出来的环境,而是内核对同一个进程返回不同系统信息的结果。
cgroup 实现资源限制
仅靠 namespace 还不够——进程可以无节制地吃光 CPU 或内存。cgroup 把这个进程(及其子进程)纳入一个控制组,硬性设定它的资源上限:比如最多用 2 核 CPU、最多占 512MB 内存。宿主机调度器会按这些规则分配资源,相当于给进程套上了一副“资源镣铐”。
其他机制补全边界
除了两大支柱,容器还依赖更多内核能力来加固这个“特殊进程”:
- Capabilities:去掉 root 默认拥有的全部权限,只保留容器真正需要的(如绑定低端口、修改网络配置),避免提权风险;
- Seccomp:过滤掉危险的系统调用(如 reboot、kill 宿主机进程),从源头堵住攻击路径;
- LSM(如 SELinux/AppArmor):提供策略级访问控制,进一步限定进程能读写哪些文件、连接哪些地址。
镜像与运行时只是封装工具
Docker 镜像本质是一堆分层的只读文件系统 + 元数据,它不运行;Docker daemon 只是帮你调用 clone() 系统调用,并传入一堆 CLONE_NEW* 标志和 cgroup 路径;最终真正执行起来的,始终是那个被层层约束的用户态进程。你在 ps aux 里能看到它,在 /proc/[pid]/ 下能查到它的 namespace 和 cgroup 归属——它就在那儿,真实、可见、可调试。











