Docker 容器默认是"隔离"的,但容器之间、容器与宿主机之间、容器与外部网络之间怎么通信?答案就在 Docker 的网络模式中。
这篇文章把 Docker 的六种网络模式逐一拆解:原理、适用场景、实战命令和常见坑点。
一、先理解 Docker 的网络模型
Docker 使用 CNM(Container Network Model),核心组件有三个:
| 组件 | 作用 | 类比 |
|---|---|---|
| Sandbox(沙盒) | 容器的网络命名空间 | 一个独立的房间 |
| Endpoint(端点) | 连接 Sandbox 和 Network 的接口 | 房间的门 |
| Network(网络) | 一组可以互相通信的 Endpoint 集合 | 走廊/桥梁 |
Docker 内置了五种网络驱动:bridge、host、none、overlay、macvlan(以及更高效的 ipvlan)。
查看当前网络:
docker network ls输出类似:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
f6e5d4c3b2a1 host host local
e5d4c3b2a1f6 none null local二、bridge 网络(默认模式)
工作原理
每个容器启动时默认连接到 bridge 网络。Docker 在宿主机上创建一个 docker0 虚拟网桥,容器通过 veth pair(虚拟网线)连接到这个网桥上。
宿主机
┌─────────────────────────┐
│ docker0 网桥 │ ← 172.17.0.1
│ ┌─────┴─────┐ │
│ veth1 veth2 │ ← veth pair(虚拟网线)
│ │ │ │
│ ┌──┴──┐ ┌──┴──┐ │
│ │容器A │ │容器B │ │
│ │172. │ │172. │ │
│ │17.0.│ │17.0.│ │
│ │ 2 │ │ 3 │ │
│ └─────┘ └─────┘ │
└─────────────────────────┘
│ eth0
▼
外部网络容器的 eth0 通过 veth pair 连接到 docker0,然后通过 NAT(iptables MASQUERADE)访问外部网络。
实践
# 默认 bridge 启动容器
docker run -d --name web1 nginx
# 查看容器 IP
docker inspect web1 --format '{{.NetworkSettings.IPAddress}}'
# 172.17.0.2
# 容器间通信(通过 IP)
docker run -d --name web2 nginx
docker exec web1 ping 172.17.0.3
# 但无法通过容器名通信(默认 bridge 不支持 DNS)
docker exec web1 ping web2 # ❌ 失败自定义 bridge(推荐)
默认 bridge 有局限:不支持容器名自动 DNS 解析、所有容器共享相同的网络配置。创建自定义 bridge 更灵活。
# 创建自定义 bridge
docker network create --driver bridge mynet
# 容器连接到自定义 bridge
docker run -d --name app1 --network mynet nginx
docker run -d --name app2 --network mynet nginx
# 自定义 bridge 支持容器名 DNS 解析 ✅
docker exec app1 ping app2自定义 bridge 的特点:
- 容器间可通过容器名直接通信(自动 DNS)
- 独立的网络命名空间,与默认 bridge 隔离
- 可动态连接/断开容器(
docker network connect/disconnect)
端口映射
# -p 宿主机端口:容器端口
docker run -d --name web -p 8080:80 nginx
# 查看映射
docker port web
# 80/tcp -> 0.0.0.0:8080内部流程:宿主机 iptables 的 DNAT 规则将访问 0.0.0.0:8080 的流量转发到容器 172.17.0.2:80。
三、host 网络模式
容器直接使用宿主机的网络命名空间,不隔离网络。
docker run -d --name web --network host nginx特点:
| 对比 | bridge | host |
|---|---|---|
| 端口映射 | 需 -p |
不需要,直接监听宿主机端口 |
| IP 地址 | 独立的 172.17.x.x | 同宿主机 IP |
| 网络性能 | 有轻微损耗(NAT) | 零损耗,接近原生 |
| 端口冲突 | 每个容器独立端口空间 | 多个容器监听同一端口会冲突 |
# host 模式下,容器直接监听宿主机端口
docker run -d --name web --network host nginx
# 无需 -p,直接访问 http://宿主机IP:80适用场景:
- 对网络性能要求极高的场景(如日志采集器、监控代理)
- 容器需要监听宿主机大量随机端口(如服务注册中心)
- 想要容器网络完全透明无 NAT 损耗
不适用场景:
- 需要端口隔离的多容器部署
- Kubernetes Pod(K8s 强制要求独立的网络命名空间)
四、none 网络模式
容器没有网络接口,完全与网络隔离。
docker run -d --name isolated --network none alpine sleep 3600
docker exec isolated ip addr
# 1: lo: <LOOPBACK,UP,LOWER_UP> ... 只有 lo 回环接口适用场景:
- 极简安全容器,不需要任何网络访问
- 离线计算任务
- 仅执行本地文件操作的工具容器
五、overlay 网络(跨主机通信)
当容器分布在不同物理机(或不同宿主机)上时,bridge 无法直接通信。overlay 网络通过 VXLAN 隧道技术,把所有宿主机虚拟成一个大的二层网络。
宿主机A 宿主机B
┌──────────┐ ┌──────────┐
│ 容器A │ │ 容器B │
│ 10.0.0.2 │ │ 10.0.0.3 │
└────┬─────┘ └────┬─────┘
│ │
┌────┴─────┐ ┌────┴─────┐
│overlay │ VXLAN │overlay │
│网络 │◄─────────►│网络 │
└──────────┘ 隧道封装 └──────────┘使用前提
overlay 网络需要 Swarm 模式或 Docker 集群。最简单的场景是 Docker Swarm:
# 初始化 Swarm(在管理节点)
docker swarm init
# 创建 overlay 网络
docker network create -d overlay --attachable myoverlay
# 在任意集群节点启动容器并连接到 overlay
docker service create --name myservice \
--network myoverlay \
--replicas 2 \
nginx关键细节
- VXLAN 封装会带来约 5-10% 的网络性能损耗
- 需要宿主机之间 UDP 4789 端口互通(VXLAN 默认端口)
--attachable参数让普通容器(非 service)也能连接到 overlay 网络
六、macvlan 网络(二层直通)
macvlan 给容器分配一个真实的 MAC 地址,让容器像一台独立物理机一样接入局域网。
路由器
│
├── 宿主机 MAC: AA:BB:CC:DD:EE:FF IP: 192.168.1.100
│
├── 容器A MAC: 00:11:22:33:44:01 IP: 192.168.1.101
│
└── 容器B MAC: 00:11:22:33:44:02 IP: 192.168.1.102# 创建 macvlan 网络(绑定宿主机物理接口 eth0)
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
mymacvlan
# 启动容器(指定 IP)
docker run -d --name web --network mymacvlan \
--ip=192.168.1.101 nginx特点:
| 优点 | 缺点 |
|---|---|
| 无 NAT,性能极高 | 宿主机无法直接与容器通信(需额外配置) |
| 容器像普通设备一样接入局域网 | 需要交换机支持 MAC 地址学习的上限 |
| 可用于需要直接获取客户端真实 IP 的场景 | IP 地址消耗大,每个容器占一个 IP |
宿主机无法访问 macvlan 容器的解决方法(创建带 parent 接口的子接口 macvlan):
# 宿主机上创建 macvlan 子接口
ip link add mymacvlan-shim link eth0 type macvlan mode bridge
ip addr add 192.168.1.200/24 dev mymacvlan-shim
ip link set mymacvlan-shim up七、ipvlan 网络(三层直通)
ipvlan 是 macvlan 的升级版,不分配 MAC 地址,所有容器共享宿主机 MAC 地址,通过 IP 区分。
# L2 模式(同网段通信)
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
-o ipvlan_mode=l2 \
myipvlan
# L3 模式(跨网段路由)
docker network create -d ipvlan \
--subnet=10.0.1.0/24 \
--subnet=10.0.2.0/24 \
-o parent=eth0 \
-o ipvlan_mode=l3 \
myipvlan-l3macvlan vs ipvlan 对比:
| 对比项 | macvlan | ipvlan |
|---|---|---|
| MAC 地址 | 每个容器独立 MAC | 所有容器共享宿主机 MAC |
| 交换机压力 | 高(大量 MAC 学习) | 低(只有宿主机一个 MAC) |
| 性能 | 优 | 更优 |
| 支持模式 | bridge、802.1q | L2、L3 |
| 主流支持 | 广泛 | 较新,部分环境可能受限 |
八、网络模式对比总结
| 模式 | 驱动 | 隔离性 | 性能 | DNS解析 | 跨主机 | 适用场景 |
|---|---|---|---|---|---|---|
| 默认 bridge | bridge | ✅ | 一般(有 NAT) | ❌ 不支持容器名 | ❌ | 单机单体容器 |
| 自定义 bridge | bridge | ✅ | 一般(有 NAT) | ✅ 支持容器名 | ❌ | 单机多容器(推荐) |
| host | host | ❌ 不隔网络 | 最高 | 同宿主机 | ❌ | 高性能/端口密集场景 |
| none | null | ✅ 完全隔离 | - | - | ❌ | 离线/安全容器 |
| overlay | overlay | ✅ | 中等(VXLAN) | ✅ | ✅ | Swarm/K8s 集群 |
| macvlan | macvlan | ✅ | 高(无 NAT) | ❌ | ✅ | 容器直接连入物理网 |
| ipvlan | ipvlan | ✅ | 最高 | ❌ | ✅ | MAC 地址受限场景 |
九、常见问题与排查
容器能 ping 通 IP 但 ping 不通容器名
# 原因:容器在默认 bridge,不在自定义 bridge
# 解决:创建自定义 bridge 并连接
docker network create mynet
docker network connect mynet containerA
docker network connect mynet containerBhost 模式下端口冲突
# 错误:端口已被占用
docker: Error response from daemon: driver failed programming external connectivity on endpoint ...
# 解决:换端口或停止占用该端口的进程overlay 网络跨主机不通
# 1. 检查防火墙是否放行 VXLAN 端口(UDP 4789)
# 2. 确认 Swarm 节点之间的网络连通性
# 3. 检查 IP 转发是否开启
sysctl net.ipv4.ip_forward端口映射后外部无法访问
# 1. 确认容器监听的是 0.0.0.0 而非 127.0.0.1
docker exec web netstat -tlnp
# 2. 确认宿主机防火墙放行了映射端口
sudo ufw status | grep 8080
# 3. 检查 iptables 规则是否被覆盖
sudo iptables -t nat -L DOCKER -n十、选择网络模式的最佳实践
┌── 单机部署 ──┐
│ │
需要DNS解析? 不需要DNS解析?
│ │
自定义 bridge 默认 bridge
│
┌────────┴────────┐
│ │
多容器通信 单容器运行
│ │
自定义 bridge 默认 bridge 够用
┌── 多机部署 ──┐
│ │
Docker Swarm Kubernetes
│ │
overlay 网络 CNI 插件(Flannel/Calico)
┌── 特殊场景 ──┐
│ │
零 NAT 损耗 MAC 地址受限
│ │
macvlan/ipvlan ipvlan L2一句话总结:
- 单机多容器 → 自定义 bridge(兼顾隔离和 DNS 解析)
- 高性能/端口密集 → host(零损耗但有冲突风险)
- 集群多主机 → overlay(跨主机透明通信)
- 物理网络直通 → macvlan/ipvlan(容器就像真机器)
- 完全隔离 → none(连网络都不要)