容器网络与端口发布
定义
容器网络指工作负载如何获得 IP、路由、DNS
以及与其他工作负载通信的路径。端口发布(publish)指在宿主(或中继进程)上监听一个地址,把到达的连接转发到工作负载内部的端口。-p 8080:80
的含义是:宿主 8080 上的 TCP 连接,被转发到工作负载网络命名空间中的 80
端口。
网络隔离与端口发布是两件事。没有 -p
时,工作负载仍可以拥有自己的网络栈;只是宿主网络上的客户端不能直接打到它的监听端口。
问题背景
若所有容器共用宿主网络命名空间,则端口冲突无法避免,防火墙规则也难以按实例拆分。若完全断网,则多服务应用无法互访。因此需要一种介于「共用宿主网卡」与「完全离线」之间的模型:每个实例有独立的网络视野,必要时再通过显式发布或命名网络把选定流量引入。
机制说明
独立网络栈
在共享内核模型中,独立网络栈来自 network
namespace:独立的网卡、地址、路由表与端口号空间。容器内的
80 与宿主的 80 不是同一个端口。在 MicroVM
模型中,独立网络栈来自客户机内核,效果类似,但边界是虚拟网卡而不是宿主
namespace。
端口发布的实际含义
-p 8080:80 并不修改镜像,也不等于 Dockerfile 里的
EXPOSE。它要求产品层在宿主侧启动一个转发器(或配置
NAT),把外部连接送入工作负载。因此:
- 工作负载必须确实在内部端口上监听,否则发布成功也会连不上;
- 协议必须匹配。只声明 TCP 时,UDP 流量不会被自动接收;
- 发布面受隔离模式约束。Box 的 Sandbox GA 拒绝命名桥与静态发布端口,见下节。
命名网络
network create backend --subnet 10.89.0.0/24
创建一块逻辑二层 / 三层网络,加入该网络的服务可以用名称发现彼此。Compose
通常自动为同一文件中的服务提供默认网络,从而避免手写 IP。
在 Box 中的位置
Box 的网络面按隔离路径分裂,且没有静默回退。
| 路径 | 当前网络能力 | 被拒绝的能力 |
|---|---|---|
| MicroVM | TSI、命名桥、对等发现、TCP 发布、有界 ACL / YAML Compose 子集 | 依主机资格而定;Windows 资格验证路径限制更多 |
| Sandbox GA | 私有 netns、仅 loopback、代际围栏的 Runtime Service 主机 loopback 中继 | 命名桥与静态发布端口 |
- 产品网络逻辑位于
src/runtime/src/network/,核心类型在src/core/src/network.rs、port.rs。 - MicroVM 的桥接与 NAT 由
src/netproxy/(passt)承担。 - Sandbox 附件在
local_execution/oci_network_attachments.rs。证据见docs/sandbox-ga-evidence.md。 - 最近的修复
d729a83d(fix(net): admit static UDP published ports in netproxy)针对 MicroVM netproxy 的静态 UDP 发布,不改变 Sandbox GA 对发布端口的拒绝。
验证命令
MicroVM 路径(省略 isolation):
a3s-box run -d --name web --memory 1g -p 8080:80 nginx:alpine |
Sandbox 路径上,同样的 -p
应在预检阶段失败,而不是降级为「启动成功但端口未发布」。这一失败是契约,不是缺陷。
相关与易混
- 相关:namespace 与 cgroup、Compose、Sandbox(共享内核)
- 易混:
EXPOSE只是镜像元数据。-p才是发布。Sandbox 与 MicroVM 的网络能力不同,不能用同一条 compose 文件假设二者行为一致。