Docker 容器网络模型深度解析:从 Linux 内核到生产实践的网络架构完整指南

作者:云原生架构师
技术栈:Docker, Linux Kernel, Network Namespace, veth pair, iptables, Bridge
难度等级:★★★★★(专家级)
预计阅读时间:100 分钟


目录

  1. 引言:容器网络的复杂性与挑战
  2. Linux 网络命名空间深度解析
  3. Docker 默认网络模型架构
  4. 容器访问外网的完整流程
  5. 外网访问容器的完整流程
  6. iptables 规则详解
  7. Docker 四种网络模型
  8. 容器间通信机制
  9. 网络性能优化
  10. 故障排查实战
  11. 生产环境最佳实践
  12. 总结与前沿技术

1. 引言:容器网络的复杂性与挑战

1.1 容器网络的三大核心问题

问题 1:隔离性

如何实现容器间的网络隔离?
- 每个容器独立的 IP 地址
- 每个容器独立的端口空间
- 每个容器独立的路由表
- 每个容器独立的防火墙规则

技术实现:
- Network Namespace(网络命名空间)
- 独立的网络设备(eth0, lo)
- 独立的协议栈

问题 2:连通性

如何实现容器与外部通信?
- 容器访问外网(出站流量)
- 外网访问容器(入站流量)
- 容器间通信(横向流量)
- 跨主机容器通信(Overlay 网络)

技术实现:
- NAT(网络地址转换)
- 端口映射
- 网桥(Bridge)
- VXLAN 隧道

问题 3:性能

如何保证网络性能?
- 减少 NAT 转换次数
- 减少数据包复制
- 利用内核旁路技术
- 优化 MTU 设置

性能指标:
- 吞吐量:10 Gbps+
- 延迟:<0.1ms
- CPU 占用:<10%

1.2 Docker 网络架构演进

┌─────────────────────────────────────────────────────┐
│  Docker 网络架构演进                                 │
├─────────────────────────────────────────────────────┤
│  2013: Docker 0.1                                   │
│  - 使用网桥 + NAT                                   │
│  - 简单的端口映射                                   │
│  - 无网络隔离                                       │
│                                                       │
│  2014: Docker 0.7                                   │
│  - 引入 Network Namespace                           │
│  - 容器网络隔离                                     │
│  - veth pair 实现                                   │
│                                                       │
│  2015: Docker 1.9                                   │
│  - 引入 Docker Network                              │
│  - 支持多种网络驱动                                 │
│  - 支持用户自定义网络                               │
│                                                       │
│  2016: Docker 1.12                                  │
│  - 引入 Overlay 网络                                │
│  - 支持跨主机通信                                   │
│  - 内置 DNS 服务                                    │
│                                                       │
│  2018: Docker 18.06                                 │
│  - 引入 eBPF 网络加速                              │
│  - 支持 IPvLAN                                      │
│  - 更好的性能优化                                   │
└─────────────────────────────────────────────────────┘

2. Linux 网络命名空间深度解析

2.1 什么是 Network Namespace

技术定义

Network Namespace = 独立的网络协议栈

包含:
├── 网络设备(eth0, lo, ...)
├── IP 地址和子网掩码
├── 路由表
├── 防火墙规则(iptables)
├── 套接字(sockets)
└── /proc/net 目录

命名空间隔离效果

宿主机 Network Namespace:
┌─────────────────────────────────────┐
│ eth0: 192.168.1.100/24             │
│ docker0: 172.17.0.1/16             │
│ 路由表:                           │
│   default via 192.168.1.1          │
│   172.17.0.0/16 dev docker0        │
│ iptables 规则                       │
└─────────────────────────────────────┘

容器 Network Namespace:
┌─────────────────────────────────────┐
│ eth0: 172.17.0.2/16                │
│ lo: 127.0.0.1                      │
│ 路由表:                           │
│   default via 172.17.0.1           │
│   127.0.0.0/8 dev lo               │
│ 无 iptables 规则                    │
└─────────────────────────────────────┘

2.2 创建和操作 Network Namespace

手动创建命名空间

# 创建新的 Network Namespace
ip netns add ns1

# 查看命名空间
ip netns list
# 输出:ns1

# 在命名空间中执行命令
ip netns exec ns1 ip addr
# 输出:仅显示 lo 接口

# 进入命名空间
ip netns exec ns1 bash
# 现在你在 ns1 的命名空间中

查看进程的命名空间

# 获取容器 PID
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' nginx)

# 查看命名空间
ls -l /proc/$CONTAINER_PID/ns/net
# 输出:net:[4026532460]

# 比较宿主机和容器的命名空间
ls -l /proc/1/ns/net
ls -l /proc/$CONTAINER_PID/ns/net
# 输出不同的 inode,说明在不同命名空间

2.3 veth pair(虚拟网线)

veth pair 原理

veth pair = 两个虚拟网络接口 + 点对点连接

特点:
1. 成对出现(A 和 B)
2. 数据从 A 进,从 B 出
3. 数据从 B 进,从 A 出
4. 可以跨越命名空间

┌─────────────┐         ┌─────────────┐
│  Namespace1 │         │  Namespace2 │
│             │         │             │
│   veth-A    │◄───────►│   veth-B    │
│             │         │             │
└─────────────┘         └─────────────┘
      │                       │
   容器内                 宿主机

创建 veth pair

# 创建 veth pair
ip link add veth0 type veth peer name veth1

# 查看 veth pair
ip link show
# 输出:
# 3: veth0@if4: <BROADCAST,MULTICAST> ...
# 4: veth1@if3: <BROADCAST,MULTICAST> ...

# 移动 veth1 到另一个命名空间
ip link set veth1 netns ns1

# 现在:
# veth0 在宿主机
# veth1 在 ns1 命名空间

3. Docker 默认网络模型架构

3.1 Docker 网络组件

docker0 网桥

# 查看 docker0 网桥
ip addr show docker0

# 输出:
# 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
#     link/ether 02:42:ac:11:00:01
#     inet 172.17.0.1/16 brd 172.17.255.255
#     inet6 fe80::42:acff:fe11:1/64 ...

# 功能:
# 1. 连接所有容器
# 2. 分配 IP 地址(172.17.0.0/16)
# 3. 路由转发
# 4. NAT 转换

veth pair 连接

宿主机:
┌─────────────────────────────────────┐
│  docker0 (172.17.0.1)               │
│       │                             │
│    veth1234567                      │
│       │                             │
└───────┼─────────────────────────────┘
        │ veth pair
        │
┌───────┼─────────────────────────────┐
│       │ 容器 Network Namespace      │
│    eth0 (172.17.0.2)                │
│       │                             │
│    nginx 进程                        │
└─────────────────────────────────────┘

3.2 完整的网络架构

外部网络

容器 2 网络命名空间

容器 1 网络命名空间

宿主机网络命名空间

物理网卡 eth0
192.168.1.100

docker0 网桥
172.17.0.1

veth1234567

veth7654321

iptables NAT 规则

eth0
172.17.0.2

Nginx:80

eth0
172.17.0.3

Redis:6379

互联网

3.3 IP 地址分配机制

IPAM(IP Address Management)

# 查看网络配置
docker network inspect bridge

# 输出:
# {
#   "Name": "bridge",
#   "Driver": "bridge",
#   "IPAM": {
#     "Driver": "default",
#     "Config": [
#       {
#         "Subnet": "172.17.0.0/16",
#         "Gateway": "172.17.0.1"
#       }
#     ]
#   }
# }

IP 分配流程

docker0 Bridge IPAM Driver Docker Daemon docker0 Bridge IPAM Driver Docker Daemon 请求 IP 地址 查找可用 IP 返回 172.17.0.2 创建 veth pair 分配 IP 172.17.0.2 连接到网桥 更新 ARP 表

4. 容器访问外网的完整流程

4.1 数据包路径详解

容器访问外网(例如访问 8.8.8.8:53)

1. 发送数据包
2. 查找路由表
3. ARP 解析
4. 数据包到达
5. 转发到
6. 匹配 NAT 规则
7. MASQUERADE
8. 源地址转换
9. 发送到

容器内 Nginx 进程

容器 eth0

默认网关 172.17.0.1

veth pair

docker0 网桥

PREROUTING 链

DOCKER 链

POSTROUTING 链

物理网卡 eth0

外部网络 8.8.8.8

4.2 逐步详解

步骤 1:容器内发送数据包

# 在容器内执行
docker exec nginx curl -I https://8.8.8.8

# 数据包信息:
# 源 IP: 172.17.0.2
# 源端口:随机(例如 50000)
# 目标 IP: 8.8.8.8
# 目标端口:443

步骤 2:查找路由表

# 容器内路由表
docker exec nginx ip route show

# 输出:
# default via 172.17.0.1 dev eth0
# 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2
# 127.0.0.0/8 dev lo scope link

# 匹配默认路由:via 172.17.0.1

步骤 3:ARP 解析网关 MAC 地址

# 查看 ARP 缓存
docker exec nginx arp -a

# 输出:
# ? (172.17.0.1) at 02:42:ac:11:00:01 [ether] on eth0

# 如果没有缓存,发送 ARP 请求:
# "Who has 172.17.0.1? Tell 172.17.0.2"
# docker0 回复:"172.17.0.1 is at 02:42:ac:11:00:01"

步骤 4-5:通过 veth pair 到达 docker0

数据包到达 docker0 网桥:
┌─────────────────────────────────────┐
│  docker0 网桥                        │
│  ┌─────────────────────────────┐   │
│  │ 端口 1: veth1234567          │   │ ← 来自容器
│  │ 端口 2: veth7654321          │   │
│  │ 端口 3: eth0 (物理网卡)      │   │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘

网桥根据 MAC 地址表转发到物理接口

步骤 6-8:iptables NAT 转换

# 查看 NAT 规则
iptables -t nat -L POSTROUTING -n -v

# 输出:
# Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
#  pkts bytes target     prot opt in     out     source               destination
#  1000  80000 MASQUERADE  all  --  *      !docker0 172.17.0.0/16       0.0.0.0/0

# MASQUERADE 规则:
# - 源地址:172.17.0.2 → 192.168.1.100
# - 源端口:50000 → 随机端口(例如 60000)
# - 目标地址:8.8.8.8(不变)
# - 目标端口:443(不变)

步骤 9:发送到外部网络

# 物理网卡发送数据包
tcpdump -i eth0 -n host 8.8.8.8

# 输出:
# 192.168.1.100.60000 > 8.8.8.8.443: Flags [S], seq 1234567890

4.3 完整的数据包变化

数据包在传输过程中的变化

容器内:
┌─────────────────────────────────────┐
│ 源 IP: 172.17.0.2                   │
│ 源端口:50000                       │
│ 目标 IP: 8.8.8.8                    │
│ 目标端口:443                       │
└─────────────────────────────────────┘
        │
        │ 经过 MASQUERADE
        ▼
宿主机外网:
┌─────────────────────────────────────┐
│ 源 IP: 192.168.1.100                │ ← 变化
│ 源端口:60000                       │ ← 变化
│ 目标 IP: 8.8.8.8                    │ ← 不变
│ 目标端口:443                       │ ← 不变
└─────────────────────────────────────┘

5. 外网访问容器的完整流程

5.1 端口映射配置

Docker 端口映射

docker run -d -p 8080:80 --name nginx nginx:alpine

# 参数说明:
# -p 8080:80
#   宿主机端口:8080
#   容器端口:80

查看端口映射

# 查看端口映射
docker port nginx

# 输出:
# 80/tcp -> 0.0.0.0:8080

# 查看 iptables 规则
iptables -t nat -L DOCKER -n -v

# 输出:
# Chain DOCKER (1 references)
#  pkts bytes target     prot opt in     out     source               destination
#   100  6000 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80

5.2 外网访问容器的数据包路径

1. 发送数据包
2. PREROUTING 链
3. DNAT 转换
4. 转发到
5. 容器 eth0
6. 响应数据包
7. docker0
8. POSTROUTING 链
9. SNAT 转换
10. 返回外部

外部用户 192.168.1.50

宿主机 eth0

DOCKER 链

docker0 网桥

veth1234567

容器 Nginx:80

5.3 逐步详解

步骤 1:外部用户发送请求

# 外部用户执行
curl http://192.168.1.100:8080

# 数据包信息:
# 源 IP: 192.168.1.50
# 源端口:45000
# 目标 IP: 192.168.1.100
# 目标端口:8080

步骤 2-3:PREROUTING 链 DNAT 转换

# 查看 DNAT 规则
iptables -t nat -L PREROUTING -n -v

# 输出:
# Chain PREROUTING (policy ACCEPT)
#  pkts bytes target     prot opt in     out     source               destination
#  1000  80000 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

# DOCKER 链规则:
iptables -t nat -L DOCKER -n -v

# 输出:
# Chain DOCKER (1 references)
#  pkts bytes target     prot opt in     out     source               destination
#   100  6000 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80

# DNAT 转换:
# - 目标 IP: 192.168.1.100 → 172.17.0.2
# - 目标端口:8080 → 80
# - 源 IP: 192.168.1.50(不变)
# - 源端口:45000(不变)

步骤 4-5:转发到容器

数据包到达 docker0 网桥:
┌─────────────────────────────────────┐
│  docker0 网桥                        │
│  ┌─────────────────────────────┐   │
│  │ 端口 1: veth1234567          │   │ → 到容器
│  │ 端口 2: veth7654321          │   │
│  │ 端口 3: eth0 (物理网卡)      │   │ ← 来自外部
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘

网桥根据目标 IP(172.17.0.2)转发到对应端口

步骤 6:容器内 Nginx 处理请求

# 容器内 Nginx 接收请求
docker exec nginx tail -f /var/log/nginx/access.log

# 输出:
# 192.168.1.50 - - [11/Mar/2026:10:00:00 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.68.0"

# 注意:Nginx 看到的是真实客户端 IP(192.168.1.50)

步骤 7-10:响应数据包返回

# 容器发送响应
# 源 IP: 172.17.0.2
# 源端口:80
# 目标 IP: 192.168.1.50
# 目标端口:45000

# 经过 docker0 转发到 POSTROUTING 链
# SNAT 转换(反向 NAT):
# - 源 IP: 172.17.0.2 → 192.168.1.100
# - 源端口:80 → 8080

# 返回外部用户

5.4 完整的数据包变化

入站数据包变化

外部网络:
┌─────────────────────────────────────┐
│ 源 IP: 192.168.1.50                 │
│ 源端口:45000                       │
│ 目标 IP: 192.168.1.100              │ ← 宿主机 IP
│ 目标端口:8080                      │ ← 映射端口
└─────────────────────────────────────┘
        │
        │ 经过 DNAT
        ▼
容器内:
┌─────────────────────────────────────┐
│ 源 IP: 192.168.1.50                 │ ← 不变
│ 源端口:45000                       │ ← 不变
│ 目标 IP: 172.17.0.2                 │ ← 变化
│ 目标端口:80                        │ ← 变化
└─────────────────────────────────────┘

6. iptables 规则详解

6.1 Docker 创建的 iptables 链

完整的 iptables 结构

# 查看 NAT 表
iptables -t nat -L -n -v

# 输出:
# Chain PREROUTING (policy ACCEPT)
#  target     prot opt source               destination
#  DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

# Chain INPUT (policy ACCEPT)
#  target     prot opt source               destination

# Chain OUTPUT (policy ACCEPT)
#  target     prot opt source               destination
#  DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

# Chain POSTROUTING (policy ACCEPT)
#  target     prot opt source               destination
#  MASQUERADE  all  --  *      !docker0 172.17.0.0/16       0.0.0.0/0
#  MASQUERADE  all  --  *      !br-xxx    172.18.0.0/16       0.0.0.0/0

# Chain DOCKER (2 references)
#  target     prot opt source               destination
#  DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80
#  DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3306 to:172.17.0.3:3306

6.2 NAT 规则详解

PREROUTING 链

# PREROUTING 链规则
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

# 说明:
# -m addrtype: 匹配地址类型
# --dst-type LOCAL: 目标地址是本地地址
# -j DOCKER: 跳转到 DOCKER 链

DOCKER 链

# DOCKER 链规则(端口映射)
-A DOCKER -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

# 说明:
# -p tcp: TCP 协议
# -m tcp --dport 8080: 目标端口 8080
# -j DNAT: 目标 NAT
# --to-destination 172.17.0.2:80: 转发到容器

POSTROUTING 链

# POSTROUTING 链规则(容器访问外网)
-A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE

# 说明:
# -s 172.17.0.0/16: 源地址是容器网段
# ! -d 172.17.0.0/16: 目标地址不是容器网段
# -j MASQUERADE: 源地址伪装(动态 NAT)

6.3 规则匹配流程

容器访问外网的规则匹配

数据包:172.17.0.2:50000 → 8.8.8.8:443

1. PREROUTING 链
   - 不匹配(目标不是本地地址)
   - 跳过

2. FORWARD 链
   - 匹配:-s 172.17.0.0/16
   - 允许转发

3. POSTROUTING 链
   - 匹配:-s 172.17.0.0/16 ! -d 172.17.0.0/16
   - 执行 MASQUERADE
   - 源地址变为 192.168.1.100

外网访问容器的规则匹配

数据包:192.168.1.50:45000 → 192.168.1.100:8080

1. PREROUTING 链
   - 匹配:--dst-type LOCAL
   - 跳转到 DOCKER 链

2. DOCKER 链
   - 匹配:--dport 8080
   - 执行 DNAT
   - 目标地址变为 172.17.0.2:80

3. FORWARD 链
   - 匹配:-d 172.17.0.2
   - 允许转发

4. 容器接收数据包

7. Docker 四种网络模型

7.1 Bridge 模式(默认)

架构

┌─────────────────────────────────────────────────────┐
│  Bridge 网络模型                                     │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │  Container1 │  │  Container2 │  │  Container3 │ │
│  │  172.17.0.2 │  │  172.17.0.3 │  │  172.17.0.4 │ │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │
│         │                │                │         │
│         └────────────────┼────────────────┘         │
│                          │                          │
│              ┌───────────▼───────────┐             │
│              │    docker0 Bridge     │             │
│              │      172.17.0.1       │             │
│              └───────────┬───────────┘             │
│                          │                          │
│              ┌───────────▼───────────┐             │
│              │    NAT (iptables)     │             │
│              └───────────┬───────────┘             │
│                          │                          │
│              ┌───────────▼───────────┐             │
│              │   物理网卡 eth0       │             │
│              │    192.168.1.100      │             │
│              └───────────────────────┘             │
└─────────────────────────────────────────────────────┘

特点

  • 使用网桥连接容器
  • NAT 转换访问外网
  • 端口映射访问容器
  • 容器间直接通信

使用场景

  • 单机部署
  • 开发环境
  • 测试环境

7.2 Host 模式

架构

┌─────────────────────────────────────────────────────┐
│  Host 网络模型                                       │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │  Container1 │  │  Container2 │  │  Container3 │ │
│  │  直接使用    │  │  直接使用    │  │  直接使用    │ │
│  │  宿主机网络  │  │  宿主机网络  │  │  宿主机网络  │ │
│  └─────────────┘  └─────────────┘  └─────────────┘ │
│                          │                          │
│              ┌───────────▼───────────┐             │
│              │   物理网卡 eth0       │             │
│              │    192.168.1.100      │             │
│              └───────────────────────┘             │
└─────────────────────────────────────────────────────┘

注意:容器共享宿主机网络栈,无隔离

配置

docker run -d --network host nginx:alpine

特点

  • 无 Network Namespace
  • 直接使用宿主机网络
  • 无 NAT 转换
  • 性能最好

使用场景

  • 高性能需求
  • 需要绑定低端口
  • 信任的容器

7.3 None 模式

架构

┌─────────────────────────────────────────────────────┐
│  None 网络模型                                       │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐                                    │
│  │  Container  │                                    │
│  │  仅 lo 接口  │                                    │
│  │  127.0.0.1  │                                    │
│  └─────────────┘                                    │
│                                                       │
│  无外部网络连接                                       │
└─────────────────────────────────────────────────────┘

配置

docker run -d --network none nginx:alpine

特点

  • 仅 loopback 接口
  • 完全隔离
  • 最安全

使用场景

  • 完全隔离的容器
  • 批量处理任务
  • 安全敏感应用

7.4 Container 模式

架构

┌─────────────────────────────────────────────────────┐
│  Container 网络模型                                   │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐                  │
│  │  Container1 │  │  Container2 │                  │
│  │  (主容器)   │◄──┤  (共享)     │                  │
│  │  eth0       │  │  使用 C1 网络 │                  │
│  └─────────────┘  └─────────────┘                  │
└─────────────────────────────────────────────────────┘

配置

# 创建主容器
docker run -d --name container1 nginx:alpine

# 创建共享容器
docker run -d --name container2 --network container:container1 busybox

特点

  • 共享 Network Namespace
  • 相同的 IP、端口、路由表
  • 通过 localhost 通信

使用场景

  • Sidecar 模式
  • 服务网格(Service Mesh)
  • 日志收集

8. 容器间通信机制

8.1 同一网桥下的容器通信

直接通信(无需 NAT)

# 容器 1: 172.17.0.2
# 容器 2: 172.17.0.3

# 容器 1 访问容器 2
docker exec container1 curl http://172.17.0.3:80

数据包路径

容器 1 (172.17.0.2)
    │
    │ veth1234567
    │
    ▼
docker0 网桥
    │
    │ veth7654321
    │
    ▼
容器 2 (172.17.0.3)

不经过 NAT,直接转发

性能

  • 延迟:<0.1ms
  • 吞吐量:接近线速
  • CPU 占用:低

8.2 使用容器名通信

Docker 内置 DNS

# 创建自定义网络
docker network create my-network

# 运行容器
docker run -d --name web --network my-network nginx
docker run -d --name db --network my-network mysql

# 通过容器名访问
docker exec web curl http://db:3306

DNS 解析过程

DB 容器 Docker DNS Web 容器 DB 容器 Docker DNS Web 容器 查询 db 的 IP 查找网络配置 返回 172.18.0.3 访问 172.18.0.3:3306

8.3 跨主机容器通信

Overlay 网络

# 初始化 Swarm
docker swarm init

# 创建 Overlay 网络
docker network create \
  --driver overlay \
  --subnet 10.0.0.0/24 \
  my-overlay

# 在不同节点上运行容器
# Node1: docker run --network my-overlay nginx
# Node2: docker run --network my-overlay nginx

# 跨主机通信
docker exec node1_nginx ping node2_nginx

VXLAN 隧道

Host1 (192.168.1.10)                    Host2 (192.168.1.20)
     │                                         │
     │  Container1 (10.0.0.2)                  │  Container2 (10.0.0.3)
     │       │                                 │       │
     │       │ 1. 发送数据包                   │       │
     │       │────────────────────────────────►│       │
     │       │   目标:10.0.0.3                │       │
     │       │                                 │       │
     │  ┌────▼────┐                           │       │
     │  │ VXLAN0  │                           │       │
     │  │ VNI:123 │                           │       │
     │  └────┬────┘                           │       │
     │       │ 2. VXLAN 封装                   │       │
     │       │ 外层 IP: 192.168.1.20          │       │
     │       │ 外层 UDP: 4789                 │       │
     │       │────────────────────────────────►│       │
     │       │                                 │  ┌────▼────┐
     │       │                                 │  │ VXLAN0  │
     │       │                                 │  │ VNI:123 │
     │       │                                 │  └────┬────┘
     │       │                                 │       │
     │       │                                 │       │ 3. 解封装
     │       │                                 │       │▼
     │       │                                 │       │Container2

9. 网络性能优化

9.1 MTU 优化

MTU 问题

# 查看 MTU
ip link show docker0

# 输出:
# 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
#     link/ether 02:42:ac:11:00:01
#     mtu 1500

# 问题:
# 如果物理网络 MTU < 1500
# 数据包需要分片,性能下降

优化方案

# 创建网络时指定 MTU
docker network create \
  --opt com.docker.network.driver.mtu=1450 \
  my-network

# 或者修改 daemon.json
{
  "mtu": 1450
}

9.2 使用 Host 网络提升性能

性能对比

Bridge 模式:
- 延迟:0.3ms
- 吞吐量:9.5 Gbps
- CPU 占用:15%

Host 模式:
- 延迟:0.1ms
- 吞吐量:10 Gbps
- CPU 占用:8%

性能提升:
- 延迟:减少 67%
- 吞吐量:提升 5%
- CPU:减少 47%

9.3 使用 IPvlan

IPvlan 配置

# 创建 IPvlan 网络
docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  ipvlan-net

# 运行容器
docker run -d --network ipvlan-net --ip 192.168.1.100 nginx

优势

  • 直接连接物理网络
  • 无 NAT 转换
  • 性能接近原生

10. 故障排查实战

10.1 容器无法访问外网

排查步骤

# 1. 检查容器网络配置
docker exec container ip addr show
docker exec container ip route show

# 2. 测试连通性
docker exec container ping 8.8.8.8

# 3. 检查 DNS
docker exec container nslookup google.com

# 4. 查看 iptables 规则
iptables -t nat -L POSTROUTING -n -v

# 5. 抓包分析
docker exec container tcpdump -i eth0 -n icmp

常见问题

# 问题 1:iptables 规则丢失
# 解决:重启 Docker
systemctl restart docker

# 问题 2:DNS 配置错误
# 解决:修改 daemon.json
{
  "dns": ["8.8.8.8", "1.1.1.1"]
}

# 问题 3:路由问题
# 解决:检查路由表
ip route show

10.2 端口映射无法访问

排查步骤

# 1. 检查端口映射
docker port container

# 2. 查看 iptables 规则
iptables -t nat -L DOCKER -n -v

# 3. 检查防火墙
firewall-cmd --list-all

# 4. 查看端口占用
netstat -tlnp | grep 8080

# 5. 测试本地访问
curl http://localhost:8080

常见问题

# 问题 1:防火墙阻止
# 解决:开放端口
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload

# 问题 2:端口被占用
# 解决:更换端口
docker run -d -p 8081:80 nginx

# 问题 3:iptables 规则错误
# 解决:重启 Docker
systemctl restart docker

11. 生产环境最佳实践

11.1 网络隔离

多网络隔离

# docker-compose.yml
services:
  web:
    networks:
      - frontend
      - backend
  
  api:
    networks:
      - backend
      - database
  
  db:
    networks:
      - database

networks:
  frontend:
  backend:
  database:

网络访问控制

┌─────────────────────────────────────────────────────┐
│  网络隔离策略                                        │
├─────────────────────────────────────────────────────┤
│  Frontend Network                                    │
│  - Web 容器                                          │
│  - 可访问:Internet, Backend                        │
│                                                       │
│  Backend Network                                     │
│  - API 容器                                          │
│  - 可访问:Frontend, Database                       │
│                                                       │
│  Database Network                                    │
│  - DB 容器                                           │
│  - 可访问:Backend only                             │
└─────────────────────────────────────────────────────┘

11.2 网络监控

Prometheus 监控

# 监控容器网络指标
- container_network_receive_bytes_total
- container_network_transmit_bytes_total
- container_network_receive_errors_total
- container_network_transmit_errors_total

Grafana 仪表盘

网络监控仪表盘:
- 接收带宽(bps)
- 发送带宽(bps)
- 接收错误包数
- 发送错误包数
- 网络延迟

12. 总结与前沿技术

12.1 核心技术要点

  1. Network Namespace

    • 网络隔离的基础
    • 独立的设备、IP、路由表
  2. veth pair

    • 连接不同命名空间
    • 点对点通信
  3. docker0 网桥

    • 连接所有容器
    • 转发数据包
  4. iptables NAT

    • PREROUTING:DNAT(入站)
    • POSTROUTING:MASQUERADE(出站)

12.2 前沿技术

  1. eBPF 网络加速

    • 内核级数据包处理
    • 性能提升 10 倍
  2. Cilium

    • 基于 eBPF
    • 服务网格
    • 网络安全策略
  3. Macvlan/IPvlan

    • 直接连接物理网络
    • 更好的性能

版权声明:本文原创,转载请注明出处
参考资料

  • Docker 官方文档
  • Linux Kernel 网络文档
  • iptables 官方文档
  • CNCF 云原生网络报告

如果本文对您有帮助,欢迎点赞、收藏、转发!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐