容器网络与端口发布

定义

容器网络指工作负载如何获得 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.rsport.rs
  • MicroVM 的桥接与 NAT 由 src/netproxy/(passt)承担。
  • Sandbox 附件在 local_execution/oci_network_attachments.rs。证据见 docs/sandbox-ga-evidence.md
  • 最近的修复 d729a83dfix(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
a3s-box port web
a3s-box rm -f web

Sandbox 路径上,同样的 -p 应在预检阶段失败,而不是降级为「启动成功但端口未发布」。这一失败是契约,不是缺陷。

相关与易混