Docker 网络模式详解:bridge/host/none/container怎么选
Docker 网络模式详解:bridge/host/none/container怎么选
一、容器A ping不通容器B,你遇到过吗?
刚上手 Docker 的时候,最让人困惑的往往不是 Dockerfile,而是网络。
“我的 nginx容器怎么访问不到 MySQL 容器?”
“为什么宿主机能访问 8080,但容器之间死活不通?”
“服务部署完了,跨容器通信全靠--link硬撑,加了新服务又得重启……”
这些都是 Docker 网络没搞清楚的典型症状。
Docker 提供了 4 种单机网络模式:bridge、host、none、container,外加一个升级方案——自定义 bridge 网络。每一种都对应不同的隔离级别和通信场景,用错了轻则多写配置,重则服务不通。
这篇文章用命令 + 原理 + 场景三管齐下的方式,一次讲透。
二、先搞懂底层:网络命名空间和 veth pair
Docker 网络的底层依赖 Linux 内核的 Network Namespace 和 veth pair,理解这两个概念,后面四种模式就是一层层叠加。
1.Network Namespace(网络命名空间)
每个 Docker 容器有自己独立的网络栈:网卡、IP 地址、路由表、iptables 规则,互不干扰。
# 查看容器内的网络栈
docker exec nginx ip addr
# 宿主机上可以查看所有 network namespace
ls /var/run/docker/netns/
2.veth pair(虚拟网线)
veth pair 是一对虚拟网卡,一端插在容器里(eth0),另一端插在宿主机的 docker0 网桥上。数据从一端进,另一端出,就像一根虚拟网线。
# 宿主机上查看 veth 设备
ip link show | grep veth
有了这个基础,四种模式的差异就很清晰了——本质上就是容器网络栈和宿主机网络栈之间建立关系的不同方式。
三、四种网络模式逐一拆解
1. Bridge(默认模式)
1.1 概述
Bridge 是 Docker 的默认模式。宿主机上建一个虚拟交换机 docker0,每个容器通过 veth pair 连上去,各自有独立 IP,docker run 不加 --network 就走这个模式。
1.2 基本用法
docker run -d --name web01 nginx:alpine
docker run -d --name web02 nginx:alpine
ip addr show docker0 # 172.17.0.1/16
docker inspect web01 --format '{{.NetworkSettings.IPAddress}}' # 172.17.0.2
docker inspect web02 --format '{{.NetworkSettings.IPAddress}}' # 172.17.0.3

1.3 特性
| 特性 | 说明 |
|---|---|
| 容器间通信 | ✅ 通过 IP 互通(172.17.0.0/16) |
| 容器→外网 | ✅ NAT(MASQUERADE) |
| 外网→容器 | ✅ 需要 -p 端口映射 |
| DNS 解析 | ❌ 不支持容器名解析 |
| 适用场景 | 开发环境、单容器测试 |
1.4 NAT 数据路径
Bridge 的核心是 NAT,分两个方向:
容器 → 外网(SNAT)
容器 IP 是 172.17.0.x,私有地址公网不认识。数据包经过宿主机路由时,宿主机做一次 SNAT,把源 IP 换成宿主机公网 IP。这条规则叫 MASQUERADE——动态 SNAT,宿主机换 IP 也不会断。
iptables -t nat -L POSTROUTING -n | grep MASQUERADE
# MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
容器(172.17.0.2) → veth → docker0 → SNAT → ens32 → 公网

外网 → 容器(DNAT)
公网请求 宿主机IP:8080,通过 -p 8080:80 做 DNAT:宿主机把目标地址从 宿主机IP:8080 改写为 容器IP:80,再转发进去。
docker run -d -p 8080:80 nginx:alpine
iptables -t nat -L DOCKER -n | grep 8080
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.4:80
公网 → ens32:8080 → DNAT → docker0 → veth → 容器:80


1.5 常见的 -p 写法
| 写法 | 含义 |
|---|---|
-p 8080:80 |
所有网卡映射 |
-p 127.0.0.1:8080:80 |
仅本地回环 |
-p 8080:80/udp |
指定 UDP |
-p 8080-8090:80 |
端口范围 |
1.6 默认 bridge 的坑
容器之间只能用 IP 互访,不能用容器名。新加容器后旧容器不会自动感知。所以生产环境不推荐用默认 bridge。
2. Host 模式
2.1 概述
容器直接"借用"宿主机的网络栈,没有独立 IP,没有 NAT,性能和宿主机一样。
2.2 基本用法
docker run -d --network host --name web nginx:alpine
启动后,容器的 80 端口直接绑定在宿主机的 80 端口上。

2.3 特性
| 特性 | 说明 |
|---|---|
| 容器间通信 | ✅ 同宿主机,无隔离 |
| 容器→外网 | ✅ 直通,零损耗 |
| 外网→容器 | ✅ 无需 -p,端口直接暴露 |
| 端口冲突 | ⚠️ 容易冲突,多实例不能用同一端口 |
| 适用场景 | 高性能网络需求、监控 agent(如 Prometheus node_exporter) |
2.4 适用场景
Host 模式本质上是放弃了网络隔离。适合对网络性能要求极高、且不担心端口冲突的场景。
3. None 模式
3.1 概述
容器有独立的网络命名空间,但里面什么都没有——没有网卡,没有 IP,完全与世隔绝。
3.2 基本用法
docker run -d --network none --name isolated busybox sleep 3600
# 容器内看网络
docker exec isolated ip addr
# 输出:只有 lo 回环接口,没有 eth0

3.3 特性
| 特性 | 说明 |
|---|---|
| 容器间通信 | ❌ 完全不通 |
| 容器→外网 | ❌ 不通 |
| 外网→容器 | ❌ 不通 |
| 适用场景 | 安全沙箱、不需要网络的批处理任务、手动配置网络的特殊场景 |
3.4 适用场景
None 模式适合"我只要一个隔离的计算环境,不需要网络"的情况。也可以作为手动配置网络的起点——先 --network none,再用 ip netns 自己建网络。
4. Container 模式
4.1 概述
新容器直接"共享"另一个容器的网络栈,两个容器用同一个 IP,通过 localhost 互通。
4.2 基本用法
# 先启动一个容器(bridge 模式)
docker run -d --name main -p 8080:80 nginx
# 第二个容器共享 main 的网络栈
docker run -d --name sidecar --network container:main alpine:3.19 sleep 3600
# 在 sidecar 容器里 curl localhost:80,访问的是 main 容器的 nginx
docker exec sidecar wget -qO- http://localhost:80

4.3 特性
| 特性 | 说明 |
|---|---|
| 容器间通信 | ✅ 通过 localhost,不需要跨网络 |
| 端口 | 共享,同一端口不能重复监听 |
| 网络隔离 | ❌ 两个容器网络完全共享 |
| 适用场景 | Sidecar 模式(如 Istio envoy)、需要 localhost 通信的容器对 |
4.4 适用场景
Container 模式天然适合 Sidecar 架构。比如主容器跑业务,Sidecar 容器跑代理/日志收集,它们通过 localhost 通信,延迟最低,配置最简单。
5. 四种模式一图对比
| 维度 | Bridge | Host | None | Container |
|---|---|---|---|---|
| 独立 IP | ✅ | ❌ 共用宿主机 | ❌ 无 | ❌ 共享主容器 |
| 端口映射 | 需要 -p | 无需 -p | 无端口 | 共享主容器端口 |
| 容器名 DNS | ❌ | N/A | N/A | N/A |
| 网络性能 | 有 NAT 损耗 | 原生 | N/A | 原生(localhost) |
| 隔离性 | 中 | 低 | 高 | 低 |
| 典型场景 | 开发单机 | 监控 agent | 安全沙箱 | Sidecar |
四、自定义 bridge 网络:生产环境的标配
默认 bridge 不支持容器名 DNS 解析,自定义 bridge 解决的就是这个。
1.创建自定义网络
# 创建自定义网络
docker network create --driver bridge mynet
# 查看
docker network ls
# NETWORK ID NAME DRIVER SCOPE
# abc123def456 mynet bridge local

2.容器加入自定义网络
# 把容器加入自定义网络
docker run -d --name web --network mynet nginx:alpine
docker run -d --name app --network mynet myapp:v0.1
# 在 app 容器内直接用容器名 ping 通 db
docker exec app ping web
# PING db (172.18.0.2): 56 data bytes — 通了!

3.自定义 bridge 的三大优势
- DNS 自动解析:容器名 → IP,不用记 IP 地址
- 网络隔离:不同自定义网络之间默认不通,天然做环境隔离
- 热插拔:运行中的容器可以随时加入/退出网络
4.热插拔:运行中容器动态加入/退出网络
# 运行中的容器加入另一个网络
docker network connect mynet web01
# 容器退出网络
docker network disconnect mynet web01
五、生产环境选型速查
| 场景 | 推荐模式 |
|---|---|
| 普通 Web 应用(Nginx + App + DB) | 自定义 bridge |
| 监控 agent(Prometheus exporter) | Host |
| Sidecar 模式(代理/日志收集) | Container |
| 安全沙箱/批处理任务 | None |
| 多容器需要容器名 DNS 互访 | 自定义 bridge(不要用默认 bridge) |
| 单容器快速测试 | 默认 Bridge |
一句话口诀:单机默认桥,多服务自定义桥,高性能用 Host,Sidecar 用 Container,安全隔离用 None。
六、总结
Docker 网络没有想象中复杂:bridge 是默认隔离网络,host 交出隔离换性能,none 完全封闭,container 实现共享。真正让 Docker 网络好用起来的,是自定义 bridge——DNS 解析 + 网络隔离 + 热插拔,生产环境必学。
落地清单
- 把默认 bridge 的容器迁移到自定义 bridge,享受 DNS 解析
- Docker Compose 项目天然用自定义 bridge,直接写服务名互访
- Prometheus node_exporter、Filebeat 等网络密集型 agent 考虑 Host 模式
- Sidecar 架构优先用 Container 模式,localhost 通信延迟最低
docker network ls检查现有网络,docker network inspect查看拓扑
更多推荐


所有评论(0)