容器化2024-04-04•30 分钟阅读
Docker 网络模式完全指南:从原理到实战配置
深入讲解 Docker 的五种网络模式(bridge、host、none、container、overlay),包括工作原理、使用场景、配置方法和常见问题,帮助你彻底掌握 Docker 网络
Docker网络容器运维DevOps
Docker 网络概述
Docker 网络是容器之间以及容器与外部世界通信的基础。理解 Docker 网络模式对于构建高效、安全的容器化应用至关重要。
Docker 网络的核心概念
- 网络驱动(Network Driver):决定容器如何连接网络
- 网络命名空间(Network Namespace):隔离容器的网络栈
- 虚拟网桥(Virtual Bridge):连接容器的虚拟交换机
- veth pair:连接容器和宿主机的虚拟网卡对
Docker 支持的网络模式
Docker 提供了五种网络模式:
| 网络模式 | 说明 | 使用场景 |
|---|---|---|
| bridge | 桥接模式(默认) | 单机容器通信 |
| host | 主机模式 | 高性能网络需求 |
| none | 无网络模式 | 完全隔离的容器 |
| container | 容器模式 | 共享网络栈 |
| overlay | 覆盖网络模式 | 跨主机容器通信 |
Bridge 网络模式(桥接模式)
Bridge 是 Docker 的默认网络模式,也是最常用的模式。
工作原理
- Docker 启动时创建一个名为
docker0的虚拟网桥 - 每个容器启动时,Docker 创建一对 veth pair(虚拟网卡对)
- 一端连接到容器内部(eth0),另一端连接到 docker0 网桥
- 容器通过 docker0 网桥与其他容器和外部网络通信
宿主机
├── docker0 (172.17.0.1)
│ ├── veth1 <---> 容器1 eth0 (172.17.0.2)
│ ├── veth2 <---> 容器2 eth0 (172.17.0.3)
│ └── veth3 <---> 容器3 eth0 (172.17.0.4)
└── eth0 (宿主机网卡)
查看默认网桥
# 查看 Docker 网络列表
docker network ls
# 输出示例
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
1234567890ab host host local
abcdef123456 none null local
# 查看 bridge 网络详情
docker network inspect bridge
# 查看宿主机网桥
ip addr show docker0
# 或
ifconfig docker0
创建自定义 Bridge 网络
自定义网络比默认 bridge 更强大,支持容器名解析(DNS)。
# 创建自定义网络
docker network create --driver bridge my-network
# 指定子网和网关
docker network create \
--driver bridge \
--subnet 192.168.100.0/24 \
--gateway 192.168.100.1 \
my-custom-network
# 查看网络详情
docker network inspect my-custom-network
使用 Bridge 网络
# 使用默认 bridge 网络
docker run -d --name web1 nginx
# 使用自定义网络
docker run -d --name web2 --network my-network nginx
# 为运行中的容器连接网络
docker network connect my-network web1
# 断开网络连接
docker network disconnect my-network web1
# 指定容器 IP(仅自定义网络支持)
docker run -d --name web3 \
--network my-custom-network \
--ip 192.168.100.10 \
nginx
端口映射
Bridge 模式下,容器端口需要映射到宿主机才能被外部访问。
# 映射单个端口
docker run -d -p 8080:80 --name web nginx
# 宿主机 8080 端口 -> 容器 80 端口
# 映射多个端口
docker run -d \
-p 8080:80 \
-p 8443:443 \
--name web nginx
# 映射到随机端口
docker run -d -p 80 --name web nginx
# 查看端口映射
docker port web
# 指定监听地址
docker run -d -p 127.0.0.1:8080:80 --name web nginx
# 只允许本机访问
# 映射所有端口
docker run -d -P --name web nginx
# 自动映射 Dockerfile 中 EXPOSE 的所有端口
容器间通信
默认 bridge 网络:
# 启动两个容器
docker run -d --name web1 nginx
docker run -d --name web2 nginx
# 查看容器 IP
docker inspect web1 | grep IPAddress
# 输出:172.17.0.2
# 从 web2 访问 web1(只能用 IP)
docker exec web2 ping 172.17.0.2
自定义 bridge 网络:
# 创建自定义网络
docker network create my-net
# 启动容器
docker run -d --name web1 --network my-net nginx
docker run -d --name web2 --network my-net nginx
# 从 web2 访问 web1(可以用容器名)
docker exec web2 ping web1
# 自动 DNS 解析容器名
# 从 web2 访问 web1 的服务
docker exec web2 curl http://web1
Bridge 模式的优缺点
优点:
- ✅ 容器之间网络隔离,安全性好
- ✅ 支持端口映射,灵活性高
- ✅ 自定义网络支持容器名解析
- ✅ 适合单机部署
缺点:
- ❌ 性能略低于 host 模式(多一层 NAT)
- ❌ 端口映射可能导致端口冲突
- ❌ 不支持跨主机通信
适用场景
- 单机运行多个容器
- 需要网络隔离的应用
- Web 应用、数据库、缓存等常规服务
Host 网络模式(主机模式)
Host 模式下,容器直接使用宿主机的网络栈,不进行网络隔离。
工作原理
- 容器不会获得独立的 Network Namespace
- 容器直接使用宿主机的 IP 地址和端口
- 容器内的进程可以直接绑定宿主机的任意端口
- 没有 NAT 转换,性能最优
宿主机 (192.168.1.100)
└── eth0
├── 宿主机进程
└── 容器进程(共享网络栈)
使用 Host 网络
# 启动容器使用 host 网络
docker run -d --name web --network host nginx
# 查看容器网络配置
docker exec web ip addr
# 输出与宿主机完全相同
# 容器内的 Nginx 直接监听宿主机的 80 端口
# 无需端口映射,直接访问宿主机 IP:80
curl http://宿主机IP:80
Host 模式的特点
优点:
- ✅ 网络性能最优(无 NAT 损耗)
- ✅ 配置简单,无需端口映射
- ✅ 容器可以直接使用宿主机的网络资源
缺点:
- ❌ 容器与宿主机共享网络,隔离性差
- ❌ 端口冲突风险高
- ❌ 安全性较低
- ❌ 不支持在同一主机上运行多个相同端口的容器
适用场景
- 对网络性能要求极高的应用
- 需要监听大量端口的应用
- 网络监控、抓包工具
- 单容器部署的场景
实战示例
# 运行高性能 Web 服务
docker run -d --name nginx-high-perf \
--network host \
nginx
# 运行网络监控工具
docker run -it --rm \
--network host \
nicolaka/netshoot \
tcpdump -i eth0
# 运行需要访问宿主机服务的容器
docker run -d --name app \
--network host \
myapp:latest
None 网络模式(无网络模式)
None 模式下,容器拥有独立的 Network Namespace,但不进行任何网络配置。
工作原理
- 容器有独立的网络栈
- 只有 loopback 接口(127.0.0.1)
- 没有其他网络接口
- 完全与外界隔离
使用 None 网络
# 启动无网络容器
docker run -d --name isolated --network none nginx
# 查看容器网络
docker exec isolated ip addr
# 输出:
# 1: lo: <LOOPBACK,UP,LOWER_UP>
# inet 127.0.0.1/8 scope host lo
# 容器无法访问外网
docker exec isolated ping 8.8.8.8
# ping: bad address '8.8.8.8'
手动配置网络
如果需要,可以手动为 none 模式的容器配置网络:
# 创建容器
docker run -d --name test --network none busybox sleep 3600
# 获取容器 PID
PID=$(docker inspect -f '{{.State.Pid}}' test)
# 创建 veth pair
ip link add veth0 type veth peer name veth1
# 将 veth1 加入容器的网络命名空间
ip link set veth1 netns $PID
# 配置容器内的网络
nsenter -t $PID -n ip addr add 192.168.1.2/24 dev veth1
nsenter -t $PID -n ip link set veth1 up
None 模式的优缺点
优点:
- ✅ 最高级别的网络隔离
- ✅ 安全性最高
- ✅ 适合不需要网络的任务
缺点:
- ❌ 无法与外界通信
- ❌ 使用场景有限
适用场景
- 数据处理任务(不需要网络)
- 安全敏感的应用
- 需要完全自定义网络配置的场景
Container 网络模式(容器模式)
Container 模式下,新容器与指定的已存在容器共享网络栈。
工作原理
- 新容器不创建独立的 Network Namespace
- 与指定容器共享 IP 地址、端口范围、路由表
- 两个容器的网络配置完全相同
- 类似于 Kubernetes 的 Pod 网络模型
容器1 (Network Namespace)
├── eth0 (172.17.0.2)
├── 容器1 进程
└── 容器2 进程(共享网络栈)
使用 Container 网络
# 启动第一个容器
docker run -d --name web nginx
# 启动第二个容器,共享 web 的网络
docker run -d --name sidecar \
--network container:web \
busybox sleep 3600
# 查看两个容器的网络配置
docker exec web ip addr
docker exec sidecar ip addr
# 输出完全相同
# sidecar 可以通过 localhost 访问 web
docker exec sidecar wget -O- http://localhost:80
实战场景:Sidecar 模式
# 主应用容器
docker run -d --name app \
-p 8080:8080 \
myapp:latest
# 日志收集 sidecar
docker run -d --name log-collector \
--network container:app \
-v /var/log:/logs \
fluentd:latest
# 监控 sidecar
docker run -d --name metrics \
--network container:app \
prom/node-exporter
Container 模式的优缺点
优点:
- ✅ 容器间通信使用 localhost,性能高
- ✅ 简化网络配置
- ✅ 适合 Sidecar 模式
缺点:
- ❌ 容器间网络不隔离
- ❌ 端口冲突风险
- ❌ 一个容器停止会影响另一个
适用场景
- Sidecar 模式(日志收集、监控、代理)
- 需要紧密协作的容器
- 模拟 Kubernetes Pod 行为
Overlay 网络模式(覆盖网络)
Overlay 网络用于跨主机的容器通信,是 Docker Swarm 和 Kubernetes 的基础。
工作原理
- 基于 VXLAN 技术实现
- 在物理网络之上创建虚拟网络
- 容器可以跨主机通信,就像在同一网络
- 需要 key-value 存储(etcd、Consul)或 Swarm 模式
主机1 (192.168.1.10) 主机2 (192.168.1.20)
├── 容器1 (10.0.0.2) ├── 容器3 (10.0.0.4)
└── 容器2 (10.0.0.3) └── 容器4 (10.0.0.5)
│ │
└──────── Overlay 网络 ────────────┘
(VXLAN 隧道)
初始化 Swarm 模式
# 在主节点初始化 Swarm
docker swarm init --advertise-addr 192.168.1.10
# 输出加入命令,在其他节点执行
docker swarm join --token SWMTKN-xxx 192.168.1.10:2377
# 查看节点
docker node ls
创建 Overlay 网络
# 创建 overlay 网络
docker network create \
--driver overlay \
--subnet 10.0.0.0/24 \
--gateway 10.0.0.1 \
my-overlay
# 创建可附加到独立容器的 overlay 网络
docker network create \
--driver overlay \
--attachable \
my-attachable-overlay
# 查看网络
docker network ls
使用 Overlay 网络
# 创建服务(自动使用 overlay 网络)
docker service create \
--name web \
--network my-overlay \
--replicas 3 \
nginx
# 查看服务
docker service ls
docker service ps web
# 在不同主机上的容器可以互相通信
# 主机1
docker run -it --rm \
--network my-attachable-overlay \
--name test1 \
busybox
# 主机2
docker run -it --rm \
--network my-attachable-overlay \
--name test2 \
busybox
# 在 test1 中 ping test2
ping test2
Overlay 网络加密
# 创建加密的 overlay 网络
docker network create \
--driver overlay \
--opt encrypted \
secure-overlay
# 使用加密网络
docker service create \
--name secure-web \
--network secure-overlay \
nginx
Overlay 模式的优缺点
优点:
- ✅ 支持跨主机容器通信
- ✅ 自动服务发现和负载均衡
- ✅ 支持网络加密
- ✅ 适合微服务架构
缺点:
- ❌ 配置复杂,需要 Swarm 或 K8s
- ❌ 性能略低于 bridge(封装开销)
- ❌ 需要额外的网络组件
适用场景
- 跨主机的容器编排(Swarm、Kubernetes)
- 微服务架构
- 分布式应用
- 需要服务发现和负载均衡的场景
网络故障排查
常用排查命令
# 查看容器网络配置
docker inspect <container_id> | grep -A 20 NetworkSettings
# 进入容器网络命名空间
docker exec -it <container_id> bash
# 查看容器 IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_id>
# 查看容器端口映射
docker port <container_id>
# 测试容器网络连通性
docker exec <container_id> ping <target>
docker exec <container_id> curl <url>
docker exec <container_id> telnet <host> <port>
# 查看容器路由表
docker exec <container_id> ip route
# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf
# 抓包分析
docker exec <container_id> tcpdump -i eth0 -w /tmp/capture.pcap
常见问题及解决
问题 1:容器无法访问外网
排查步骤:
# 1. 检查容器 DNS
docker exec <container_id> cat /etc/resolv.conf
# 2. 测试 DNS 解析
docker exec <container_id> nslookup google.com
# 3. 检查路由
docker exec <container_id> ip route
# 4. 检查宿主机 IP 转发
cat /proc/sys/net/ipv4/ip_forward
# 应该输出 1
# 5. 启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 或永久启用
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# 6. 检查 iptables NAT 规则
iptables -t nat -L -n
问题 2:容器间无法通信
排查步骤:
# 1. 检查容器是否在同一网络
docker network inspect <network_name>
# 2. 检查防火墙规则
iptables -L -n
# 3. 检查容器 IP
docker inspect <container_id> | grep IPAddress
# 4. 测试连通性
docker exec <container1> ping <container2_ip>
# 5. 检查端口是否监听
docker exec <container_id> netstat -tlnp
问题 3:端口映射不生效
排查步骤:
# 1. 检查端口映射配置
docker port <container_id>
# 2. 检查容器内服务是否启动
docker exec <container_id> netstat -tlnp | grep <port>
# 3. 检查宿主机端口是否被占用
netstat -tlnp | grep <port>
# 4. 检查防火墙
iptables -L -n | grep <port>
# 5. 检查 Docker 代理规则
iptables -t nat -L -n | grep <port>
问题 4:DNS 解析失败
解决方案:
# 方法 1:指定 DNS 服务器
docker run -d \
--dns 8.8.8.8 \
--dns 114.114.114.114 \
nginx
# 方法 2:修改 Docker 守护进程配置
cat > /etc/docker/daemon.json <<EOF
{
"dns": ["8.8.8.8", "114.114.114.114"]
}
EOF
# 重启 Docker
systemctl restart docker
# 方法 3:使用宿主机 DNS
docker run -d \
--dns-search example.com \
nginx
最佳实践
1. 网络规划
- ✅ 为不同环境使用不同的网络(开发、测试、生产)
- ✅ 使用自定义网络而非默认 bridge
- ✅ 合理规划 IP 地址段,避免冲突
- ✅ 使用有意义的网络名称
2. 安全配置
# 禁用容器间通信(默认 bridge)
docker network create \
--driver bridge \
--opt com.docker.network.bridge.enable_icc=false \
isolated-net
# 限制容器只能访问特定网络
docker run -d \
--network isolated-net \
--cap-drop=NET_RAW \
nginx
3. 监控和日志
# 查看网络统计
docker stats
# 查看网络事件
docker events --filter type=network
# 导出网络配置
docker network inspect my-net > network-config.json
4. 清理无用网络
# 查看未使用的网络
docker network ls --filter dangling=true
# 删除未使用的网络
docker network prune
# 删除指定网络
docker network rm my-net
总结
网络模式选择指南
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 单机多容器 | Bridge(自定义) | 隔离性好,支持容器名解析 |
| 高性能需求 | Host | 无 NAT 损耗,性能最优 |
| 完全隔离 | None | 安全性最高 |
| Sidecar 模式 | Container | 共享网络栈,通信高效 |
| 跨主机通信 | Overlay | 支持分布式部署 |
关键要点
✅ 默认使用自定义 bridge 网络,而非默认 bridge
✅ 生产环境避免使用 host 模式(安全风险)
✅ 合理规划网络,避免 IP 冲突
✅ 使用容器名而非 IP 地址进行通信
✅ 定期清理无用网络资源
✅ 监控网络性能和连接状态