人人都会AI编程

27.2 镜像、容器、数据卷、网络的底层 Linux 实现

更新时间:2026-07-12

Docker 并不是凭空发明了一套全新的隔离技术,而是巧妙地将 Linux 内核已有的几项基础能力进行了组合和封装。理解这些底层实现,能让你对容器的行为有精准的掌控,而不是把它当作一个黑盒。

1. 镜像:联合文件系统(UnionFS)与分层存储

Docker 镜像的分层结构,直接依赖 Linux 的联合挂载(union mount)技术,目前最常见的实现是 OverlayFS。当你执行 docker pulldocker build 时,每一层都对应一个只读的文件系统目录。OverlayFS 将这些目录堆叠成一个统一视图:下层只读,最上层可写。

本质上,运行容器时 Docker 做的是:

mount -t overlay overlay -o lowerdir=layer2:layer1,upperdir=upper,workdir=work merged
  • layer1layer2 是镜像的只读层;
  • upper 是容器的可写层(所有修改都在这里);
  • merged 就是你在容器里看到的 / 目录。

同一个基础镜像的多个容器可以共享相同的只读层,仅各自维护一个很小的 upper 层,这就是镜像复用和快速启动的根源。没有黑科技,只是 Linux 文件系统支持的正常玩法。

2. 容器:命名空间(namespace)与控制组(cgroup)

容器的隔离感来自内核的 命名空间 机制,每种资源类型有一个独立的命名空间:

  • PID 命名空间:容器内的进程 PID 从 1 开始,看不见宿主机进程,通过 clone(CLONE_NEWPID) 创建。
  • 挂载命名空间:容器拥有自己的根文件系统挂载点,/proc/sys 等也是隔离的。
  • 网络命名空间:容器有自己的网卡、IP 地址、路由表、防火墙规则。
  • UTS 命名空间:容器可以有独立的主机名和域名。
  • IPC 命名空间:隔离共享内存、信号量等进程间通信资源。
  • 用户命名空间:容器内的 root 可以映射为宿主机的普通用户,提升安全性。

lsns 命令可以直接查看当前系统的命名空间列表;进入容器的命名空间可以用 nsenter 工具,这些都是在不使用 Docker 的情况下,原生调试容器隔离问题的必备技巧。

容器的资源限制则依赖 cgroup(控制组)。docker run --memory 256m --cpus 1 这样的参数,最终会转化为在 /sys/fs/cgroup 下对应的子目录中写入限制值:

echo "256M" > /sys/fs/cgroup/memory/docker/<container_id>/memory.limit_in_bytes
echo "100000" > /sys/fs/cgroup/cpu/docker/<container_id>/cpu.cfs_quota_us

cgroup 严格保证该组内所有进程的总内存或 CPU 用量不超过设定值,这就是容器资源隔离的真相。

3. 数据卷:绑定挂载(bind mount)

Docker 的数据卷(volume)或绑定挂载主机目录,底层就是 Linux 的 bind mount 操作。当你执行:

docker run -v /host/path:/container/path …

Docker 实际执行类似:

mount --bind /host/path /var/lib/docker/.../merged/container/path

这使得宿主机和容器共享同一份 inode 和数据,任何一方的修改立即对另一方可见。这也是为什么容器删除后,宿主机上的数据依然存在——它们本来就是普通目录,只是被挂载到了容器的文件系统视图中。

理解这一点非常重要:你可以直接在宿主机上用 lscp 等工具操作这些目录,也可以用 mount | grep bind 查看当前所有的绑定挂载关系。数据卷不是 Docker 的专属存储格式,它就是 Linux 文件系统的一部分。

4. 容器网络:网络命名空间 + veth pair + 网桥 + iptables

Docker 网络模型是几个经典 Linux 网络组件的美妙组合:

  • 网络命名空间:每个容器都有独立的网络栈,有自己的 eth0 接口。
  • veth pair:虚拟以太网对,像一根网线的两头,一头插在容器内部(eth0),另一头留在宿主机的网络命名空间中,通常命名为 vethXXXX
  • 网桥(bridge):宿主机上运行一个虚拟交换机 docker0,所有容器的 veth 宿主机端都连接到这个桥上,形成一个二层网络,容器之间可以直接通过 IP 通信。
  • iptables/NAT:当容器需要访问外网时,宿主机进行源地址转换(SNAT),让容器的私有 IP 变为宿主机 IP。当外部需要访问容器的映射端口(-p 8080:80)时,宿主机进行目的地址转换(DNAT),将发往宿主机 8080 端口的流量转发到容器的 80 端口。

你可以用标准 Linux 命令直接查看这些底层对象:

ip netns list                 # 查看所有网络命名空间
ip link show type veth        # 查看所有 veth 对
bridge link show              # 看到哪些 veth 接到了 docker0 桥
iptables -t nat -L -n -v      # 查看 NAT 转发规则

这就是容器网络的全部秘密,没有专属协议,全是老旧而可靠的 Linux 网络设施。

小结

Docker 镜像就是叠加在一起的文件系统挂载;容器就是一堆命名空间和 cgroup 限制下的进程;数据卷就是 bind mount;容器网络就是独立网络栈加上 veth、网桥和 iptables。掌握这些底层原理后,排错不再局限于 docker logs,而是可以直接深入 /proc/sysmountip 命令去追踪,实现真正意义上的“洞察容器”。