首页
/ Moby 遗留网络架构详解:libnetwork 之前基于 Bridge + iptables 的单主机容器网络设计

Moby 遗留网络架构详解:libnetwork 之前基于 Bridge + iptables 的单主机容器网络设计

2026-09-04 22:30:52作者:伍霜盼Ellen

本文围绕 Moby(Docker 引擎)仓库中的 legacy.md 展开,系统梳理 libnetwork 引入之前(Docker v1.6 时期)的容器网络设计:Docker Engine 与 libcontainer 各自的职责分工、Linux Bridge 与 iptables 如何协作实现容器互联、--link/--expose 抽象与 NAT 端口映射的对外连接方案,并结合当前仓库中 bridge 驱动、iptabler 等源码说明这套"遗留"机制在现代 Moby 中的存续形态。读完本文,你可以准确理解 Docker 单主机网络的底层工作流,并知道现代 libnetwork 架构为何被提出。

文档定位:libnetwork 设计文档的"前传"

daemon/libnetwork/docs/legacy.md 是 libnetwork 文档族中的一份"TL;DR"文档,其开头明确说明:本文档是 Docker v1.6 时代网络设计的浓缩版本,更详细的操作设计请参阅对应的完整设计文档。它与 design.md 构成对照关系——后者在开篇即指出:libnetwork 的许多设计决策"汲取自 Docker v1.6 网络设计的经验教训",并引导读者阅读 legacy.md 了解旧架构。

因此,理解 legacy.md 的价值在于:它回答了"在 CNM(Container Network Model)出现之前,Docker 是如何做网络的",这也是理解 libnetwork 为何要拆分成 Controller/Driver/Network/Endpoint/Sandbox 等抽象的历史基线。

Docker v1.6 时代的网络架构:职责分工

根据 legacy.md 的描述,libnetwork 出现之前,Docker 的网络能力由两个组件共同承担

  1. Docker Engine:负责提供容器网络栈的配置(configuration for the container's networking stack)。它使用 Bridge Driver(桥接驱动)来提供单主机网络方案,底层依赖 Linux Bridge(Linux 网桥)和 iptables 实现。
  2. Libcontainer:接收 Docker Engine 给出的配置信息,负责创建必要的网络设备并将这些设备移入容器的网络命名空间(network namespace)。容器启动时使用的正是这个已配置好的命名空间。

用一句话概括旧架构的分工:Docker Engine 出"设计图纸",libcontainer 干"施工落地"。前者决定容器应该有什么样的网络栈,后者真正把 veth 设备、IP 地址、路由表写进容器的 netns 里。

Docker Engine 在这一架构中还承担了一个关键的"抽象"职责:通过 --link--expose 等简单的命令行配置项,让同一主机内的容器之间可以直接连通,且把网络配置的细节完全从容器中屏蔽掉——容器内不需要关心自己对端的 IP 是什么,也不需要手工配置路由。

单主机连接:Linux Bridge 的落地细节

legacy.md 提到 Bridge Driver 依赖 linux bridge,结合当前仓库中更完整的 network.md 文档(其内容与 v1.6 时代实现一致,描述了容器接入 docker0 网桥的完整步骤),可以把遗留架构的具体数据面还原如下:

  1. 创建网络命名空间:为容器创建一个新的 Linux 网络命名空间,该命名空间与宿主机的网络栈隔离,容器内部只能看到自己的网络设备。
  2. 创建 veth pair:创建一个 veth 设备对,一端挂到宿主机的 docker0 网桥上,另一端被移入容器的新命名空间。
  3. 分配 IP 并配置路由:在新的命名空间内,从 docker0 网段的子网中为容器分配一个 IP 地址,并把默认路由的网关设置为 docker0 的 IP 地址。

至此,bridge 模式下容器的网络配置即告完成。出站流量的路径为:容器命名空间内的路由 → veth pair → 宿主机命名空间中的 docker0 网桥 → 宿主机路由 → 宿主机物理网卡(如 eth0)→ 外部网络;入站流量则沿相反方向流动。

上述机制在当前仓库中仍有直接对应:

  • bridge.md 明确说明 bridge 驱动"默认创建一个名为 docker0 的网桥,并在网桥与每个 endpoint 之间挂一对 veth",且该驱动基于 Linux Bridging 与 iptables 提供容器连接性;
  • bridge_store.gointerface_linux.go 中依然使用 docker0 作为默认桥接设备名;
  • daemon_unix.go 中关于 docker0fixed-cidr 的注释表明,引擎至今仍区分"docker 管理的网桥(docker0)"与用户自管网桥,并在地址查找失败时回退到默认网桥逻辑——这正是遗留架构在现代代码中的直接延续。

对外连接:NAT 与端口映射

legacy.md 指出,旧架构对外部连接性(external connectivity)完全依赖 NAT 与端口映射(port-mapping)

network.md 进一步解释了其中的关键一环——masquerade(伪装)规则:容器在 docker0 子网上被分配的 IP(例如 172.17.0.2)对宿主机外部是不可见的。因此,在 Docker 引擎初始化时,会在宿主机命名空间的 nat 表 POSTROUTING 链中添加一条默认的 masquerading 规则:凡经过路由阶段、源 IP 落在 docker0 子网(172.17.0.0/16)内的出站流量,其源 IP 都被替换为路由决定的出站接口的 IP(例如 eth0 的 172.31.2.1)。文档强调:所谓 masquerade,本质上就是"把替换源 IP 固定设置为出站接口 IP 的 SNAT"。

端口映射则是这一 NAT 能力的反向运用:通过 -p 把宿主机端口转发到容器端口,使外部客户端能够触达容器内监听的服务。

这套 iptables 规则的实现,在当前仓库中由 iptabler 包统一维护,包含 network.go(网桥级 NAT/转发规则)、endpoint.go(endpoint 级端口映射规则)与 cleaner.go(规则清理)等文件,并配有 iptabler_test.go 等测试。从源码结构看,现代 bridge 驱动复用的正是 legacy 架构所依赖的那套"bridge + iptables + masquerade + port-mapping"组合,只是规则的管理权从 Docker Engine 直接操作移入了驱动内部。

遗留架构留下的"接口"

legacy 设计中面向用户的几个配置点,如今都以更规范化的形式保留在 Moby 中:

  • --net=none(即无网络模式):libnetwork 的 design.md 在"Implementations"一节中说明,内置的 null 驱动是一个"noop"实现,专门用于不需要任何网络的场景,其存在目的正是"提供对 Docker --net=none 选项的向后兼容"——这是对遗留行为最典型的兼容承诺;
  • bridge 作为默认网络bridge.md 说明 bridge 驱动"仅支持默认的 bridge 网络,不能用于其他网络",与 legacy 时代"引擎内置一个 docker0 网桥"的形态一脉相承;
  • --link/--expose 的服务抽象:旧架构中"把网络配置完全从容器中抽象掉"的理念,在 libnetwork 中被形式化为 Endpoint(服务端点)对象,design.md 在 CNM 生命周期中解释了"为什么 CreateEndpoint 与 Join 要分成两个 API"——Endpoint 代表的是可能被容器背书的"服务",资源在创建时即被保留,从而保证容器 Stop/Start 后网络行为一致。

从 Legacy 到 CNM:为什么需要 libnetwork

legacy.md 虽短,但它是理解 design.md 全部抽象的钥匙。旧架构的局限在于:网络能力被硬编码在 Docker Engine 与 libcontainer 两个具体组件中,只支持单主机场景,且驱动不可插拔。libnetwork 的 Container Network Model 用三个核心构件重构了这一模型:

  • Sandbox:容纳容器网络栈配置(接口、路由表、DNS),Linux 上的实现就是一个网络命名空间——对应 legacy 架构中 libcontainer 负责的那一层,一个 Sandbox 可以承载来自多个网络的多个 endpoint;
  • Endpoint:把 Sandbox 连接到 Network 的桥梁,实现可以是 veth pair——对应 legacy 架构中"移入命名空间的 veth 设备",一个 endpoint 只能属于一个网络和一个 Sandbox;
  • Network:能够相互直接通信的一组 Endpoint,实现可以是 Linux 网桥、VLAN 等——对应 legacy 架构中的 docker0 网桥,但被提升为可由多种 Driver 实现的对象。

design.md 同时列出了驱动生命周期(driver.CreateNetworkdriver.CreateEndpointdriver.Joindriver.Leave 等 Driver 侧 API),内置驱动包括 null、bridge、overlay 与 remote——其中 bridge 驱动继承自 legacy 时代的设计,overlay 驱动则补上了旧架构完全缺失的多主机能力。

小结

legacy.md 用一段精炼的文字固化了 Moby 网络演进史上一个关键基线:Docker Engine 出配置、libcontainer 落设备,Linux Bridge + iptables 实现单主机互联,NAT + 端口映射打通对外连接,--link/--expose 完成用户侧抽象。当前仓库中的 bridge 驱动、iptabler 规则包、null 驱动以及 bridge.md / network.md 文档,共同印证了这套遗留设计在现代 Moby 中既被兼容保留、又被 CNM 抽象所超越的事实。对需要深入排查容器网络问题的工程师而言,理解 legacy 架构是读懂 docker0、masquerade 规则和 bridge 驱动行为的前置知识。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384