Docker 网络模式选型记录
摘要
本文基于排查老项目网络问题的实操经验,梳理了 Docker 的六种网络模式。作者指出默认 Bridge 存在子网冲突风险,推荐使用 User-defined Bridge 以获得自动 DNS 和灵活性。Host 模式性能高但易冲突,Overlay 专用于集群。最终建议开发环境统一使用 User-defined Bridge,生产环境根据场景选择 Overlay 或 Macvlan,监控服务使用 Host 模式。
最近在帮同事看一个老项目的网络问题,顺便把 docker 的几种网络模式重新理了一遍。每次用都要查文档,这次记下来,希望下次能直接抄自己的笔记。
提示:本文不是文档翻译,是我自己的实操记录和踩坑史。命令在 docker 24+ / compose v2 上验证过。
背景
服务一开始是单机 docker-compose,三四个容器。后来上 swarm,节点扩到 6 个,又踩了 overlay 的几个坑。回看整个过程,我觉得网络模式的选择本质上是在隔离和互通之间找平衡。
bridge(默认)
最常用的模式,docker 0 网桥 + NAT。容器之间通过 IP 互通,但默认情况下容器之间只能用 IP 互相访问,不能用容器名,从外部访问需要端口映射。
坑:docker0 的子网有时候会和宿主机局域网冲突。比如宿主机是 172.17.0.0/16,docker bridge 默认也是 172.17.0.0/16,容器内 ping 局域网就会出问题。改 daemon.json:
适用场景:单主机开发、web 服务、不需要被局域网其他机器直连的服务。
user-defined bridge(推荐替代 default bridge)
其实 docker network create bridge my-net 创建一个自定义 bridge 比 default bridge 强很多,强烈建议不要用 default bridge:
支持自动 DNS 解析,容器名可以直接 ping(default bridge 要
--link,已废弃)可以随时
docker network connect/disconnect,不用重启容器不同网络上的容器默认隔离(更安全)
配置更灵活(子网、网关、静态 IP 都可以指定)
我现在所有本地开发都用这个,包括 compose。
host
容器和宿主机共享网络栈,没有网络隔离。性能最好(少了一层 NAT),但端口冲突是麻烦事。
坑:多实例部署会直接端口冲突,所以 --network host 几乎只能单实例用。另外,容器进程在宿主机上 ss -tlnp 看到的是容器进程而不是 docker-proxy,调试时要注意。
适用场景:对性能敏感的负载(监控 agent、网络工具、Prometheus exporter)、单实例部署、明确知道只用一份的服务。
none
容器有自己的网络栈但完全没接口。纯隔离,要靠自定义配置(slirp4netns、sysctl、或者自己写 netns 配置)联网。
我只在两种场景用过:
跑一次性计算任务,不想有网络
某些安全沙箱场景,依赖手动配置网络策略
macvlan
让容器直接拿一个真实网段上的 IP,对外看起来像物理机器。在容器和宿主机之间不能互通(除非显式开 -o macvlan_mode=bridge)。
坑(也是我栽过最痛的一个):
大多数云厂商(AWS / GCP / 阿里云 / 腾讯云)的虚拟网卡默认不开混杂模式,macvlan 直接不工作。报错是
failed to create network: cannot find parent ethernet device,或者容器能起但没 IP。要先开ip link set eth0 promisc on,但云厂商一般不允许。宿主机 ping 不通自己的 macvlan 容器(这是 macvlan 设计的限制,不是 bug)。要 host 也能通,需要桥接一个 dummy interface,麻烦。
适用:自建机房或家庭网络,需要被局域网其他机器像访问真机一样访问容器,不需要端口映射;老应用迁移,不想改架构。
ipvlan L2 / L3
macvlan 的近亲,但不复用父接口的 MAC(每个容器有独立 MAC)。对老交换机更友好(不违反 MAC 表限制)。
适用:和 macvlan 类似,但 MAC 表有限的老网络环境下更稳。我只在实验室用过,没大规模生产。
overlay
跨主机的容器网络,docker swarm / k8s 用。底层是 vxlan 封装,包会比普通包大 50 字节左右,要算 MTU。
坑:
overlay 加密(
--opt encrypted)会有显著性能损失,我测下来吞吐掉了 30%+。除非对安全有硬要求,否则不开。MTU:如果跨节点的物理网络是 1500,不调 MTU 会有大包传输问题(fragment 或丢包)。在 daemon.json 里设
"mtu": 1450。DNS:在 swarm 1.13 之前有 DNS round-robin bug,现在好多了,但偶尔还是能踩到。
适用:swarm / k8s 集群多节点通信。单节点用 overlay 纯属浪费。
选型速查
模式 | 隔离性 | 性能 | 适用 |
|---|---|---|---|
default bridge | 中 | 中 | 本地玩具 |
user-defined bridge | 中 | 中 | 单机开发、compose |
host | 无 | 高 | 单实例、性能敏感 |
none | 完全 | — | 沙箱、计算任务 |
macvlan / ipvlan | 低 | 高 | 局域网穿透、老应用 |
overlay | 中 | 中(加密后低) | swarm / k8s 集群 |
我现在的默认
本地开发一律 user-defined bridge,compose 项目里也是。生产如果是 swarm/k8s 就 overlay,物理机房特殊需求才 macvlan。host 我基本只在跑 node_exporter 这种监控 agent 时用。
另外有个不成文的规矩:同一台机器上不同项目的容器,强制用不同的 user-defined bridge,避免互相串。这条救过我至少两次。
参考资料
《Kubernetes 网络权威指南》——虽然讲 k8s,但 CNI 部分对理解容器网络很有帮助
相关文章
暂无相关文章
