容器间进程与网络完全隔离的核心是组合启用独立PID和Network Namespace。Docker默认为每个容器创建独立pidns和netns,可通过docker inspect查主进程PID,再用ls -l /proc/<pid>/ns/{pid,net}比对ID是否不同;进容器执行ps aux和ip addr show可验证进程与网络互不可见;慎用--network=container或--pid=host等共享选项,否则会主动破坏隔离。

实现容器间网络与进程的完全隔离,核心在于确保每个容器拥有独立且不共享的 PID Namespace 和 Network Namespace。Docker 默认就满足这一条件,但关键是要理解底层机制、验证是否真正生效,并避免意外破坏隔离。
确认两个命名空间已独立启用
默认情况下,Docker 为每个容器自动创建新的 pidns 和 netns。要验证是否真正隔离,不能只看命令是否运行成功,而要看内核分配的命名空间 ID 是否不同:
- 查容器主进程 PID:docker inspect -f '{{.State.Pid}}' <container_id>
- 查该 PID 对应的 PID Namespace:ls -l /proc/<pid>/ns/pid(输出类似 pid:[4026532518])
- 查该 PID 对应的 Network Namespace:ls -l /proc/<pid>/ns/net(输出类似 net:[4026532519])
- 对另一个容器重复上述步骤,对比两组数字:只要 pid:[…] 或 net:[…] 中任一数字不同,就说明对应资源已隔离
动手验证隔离效果是否真实可见
数字一致只是基础,还需在运行时确认进程和网络互不可见:
- 进容器 A 执行 ps aux:只能看到自己启动的进程(如 nginx),看不到容器 B 的任何进程
- 进容器 A 执行 ip addr show:记下 eth0 的 IP(如 172.17.0.2)
- 进容器 B 执行相同命令:得到另一个 IP(如 172.17.0.3),且看不到 A 的网卡或路由表
- 尝试从容器 A telnet 127.0.0.1 8080:即使容器 B 在监听 8080,也必然失败——因为 localhost 指的是它自己的 lo,不是宿主机或其他容器的
警惕主动打破隔离的配置选项
有些 Docker 启动参数会显式共享命名空间,导致隔离失效,必须明确知晓后果再使用:
- --network=container:<other>:两个容器共用同一 netns → IP、端口、iptables 全部一致,网络彻底不隔离
- --pid=host 或 --network=host:直接复用宿主机命名空间 → 容器内能看到所有宿主机进程或网络设备,完全丧失隔离性
- 默认不加任何网络或 PID 参数时,Docker 自动为每个容器创建全新 netns 和 pidns,这是最安全的起点
手动模拟加深理解(非生产环境)
绕过 Docker 直接操作可帮助掌握原理,例如用 unshare 创建最小隔离环境:
- 运行 sudo unshare --pid --net --fork --mount-proc /bin/bash
- 此时 ps aux 只显示当前命名空间内进程,ip link show 只看到 lo
- 若需连通外界,需额外创建 veth pair、配 IP、启转发、加 NAT —— 这正是 Docker 网桥背后做的事


















