Docker 网络配置详解
Docker 网络是容器化应用的核心组件之一,它决定了容器之间以及容器与外部世界如何通信。本文将深入讲解 Docker 的各种网络模式、配置方法和最佳实践。
目录
Docker 网络基础
1.1 网络架构概览
Docker 使用可插拔的网络架构,支持多种网络驱动:
┌─────────────────────────────────────────────────────────────┐
│ Docker Host │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ docker0 (网桥) │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │Container│ │Container│ │Container│ │ │
│ │ │ eth0 │ │ eth0 │ │ eth0 │ │ │
│ │ └───┬─────┘ └────┬────┘ └────┬────┘ │ │
│ │ └─────────────┴────────────┘ │ │
│ │ veth pair (虚拟以太网对) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ NAT/iptables │
│ │ │
│ 物理网络接口 │
└─────────────────────────────────────────────────────────────┘1.2 默认网络
安装 Docker 后,会自动创建三个默认网络:
bash
# 查看默认网络
docker network ls
NETWORK ID NAME DRIVER SCOPE
1234567890ab bridge bridge local
2345678901bc host host local
3456789012cd none null local| 网络名称 | 驱动 | 说明 |
|---|---|---|
| bridge | bridge | 默认网络,容器通过网桥通信 |
| host | host | 容器共享主机网络栈 |
| none | null | 容器无网络接口 |
1.3 网络驱动类型
| 驱动 | 用途 | 适用场景 |
|---|---|---|
| bridge | 单机容器通信 | 单主机部署 |
| host | 主机网络共享 | 高性能网络需求 |
| overlay | 跨主机通信 | Swarm 集群 |
| macvlan | MAC 地址分配 | 需要独立 IP |
| ipvlan | IPv4/IPv6 管理 | 高级网络场景 |
| none | 禁用网络 | 完全隔离 |
网络模式详解
2.1 Bridge 模式(默认)
Bridge 是 Docker 的默认网络模式,容器通过虚拟网桥 docker0 进行通信。
bash
# 查看网桥信息
ip addr show docker0
# 查看网桥详情
brctl show docker0
# 查看 iptables 规则
iptables -t nat -L -n | grep DOCKER容器网络配置示例:
bash
# 运行容器并查看网络配置
docker run -d --name web nginx:alpine
# 查看容器网络信息
docker inspect web --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
# 进入容器查看网络
docker exec web ip addr2.2 Host 模式
Host 模式下,容器直接使用主机的网络栈,不获得独立的 IP 地址。
bash
# 使用 host 网络模式
docker run -d --name web --network host nginx:alpine
# 容器将直接使用主机的 80 端口
# 无需端口映射Host 模式特点:
| 特性 | 说明 |
|---|---|
| 性能 | 无 NAT 开销,性能最好 |
| 端口冲突 | 容器端口不能与主机冲突 |
| 隔离性 | 网络隔离性最低 |
| 适用场景 | 高性能网络应用、网络诊断工具 |
2.3 None 模式
None 模式下,容器只有 loopback 接口,完全隔离网络。
bash
# 使用 none 网络模式
docker run -d --name isolated --network none alpine sleep 3600
# 验证网络隔离
docker exec isolated ip addr
# 只显示 lo 接口2.4 Container 模式
Container 模式让新容器共享另一个容器的网络命名空间。
bash
# 创建基础容器
docker run -d --name base nginx:alpine
# 创建共享网络的容器
docker run -d --name sidecar --network container:base alpine sleep 3600
# 两个容器共享相同的网络接口Bridge 网络
3.1 默认 Bridge 网络
bash
# 查看默认网桥配置
docker network inspect bridge
# 查看容器连接信息
docker network inspect bridge --format='{{json .Containers}}'默认网桥的限制:
- 容器间只能通过 IP 地址通信
- 不支持自动服务发现
- 不支持自定义 DNS
3.2 自定义 Bridge 网络
创建自定义网桥网络:
bash
# 创建自定义网络
docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
--opt com.docker.network.bridge.name=my-bridge \
my-network
# 查看网络详情
docker network inspect my-network在自定义网络中运行容器:
bash
# 运行容器并连接到自定义网络
docker run -d --name web --network my-network nginx:alpine
docker run -d --name db --network my-network postgres:15-alpine
# 容器间可以通过名称通信
docker exec web ping db3.3 多网络连接
一个容器可以连接到多个网络:
bash
# 创建多个网络
docker network create frontend
docker network create backend
# 运行容器连接到 frontend
docker run -d --name app --network frontend nginx:alpine
# 连接到额外的网络
docker network connect backend app
# 查看容器的所有网络连接
docker inspect app --format='{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}'Host 网络
4.1 使用场景
bash
# 高性能网络应用
docker run -d --network host \
--name high-performance-app \
myapp:latest
# 网络诊断工具
docker run --rm --network host \
nicolaka/netshoot \
tcpdump -i eth04.2 Host 模式注意事项
bash
# 查看主机端口使用情况
netstat -tlnp
# Host 模式下容器端口直接绑定到主机
# 需要确保端口不冲突Overlay 网络
5.1 Swarm 模式下的 Overlay
Overlay 网络用于跨主机的容器通信,需要 Docker Swarm 模式。
bash
# 初始化 Swarm
docker swarm init
# 创建 Overlay 网络
docker network create \
--driver overlay \
--subnet 10.0.0.0/16 \
--attachable \
my-overlay
# 创建使用 Overlay 网络的服务
docker service create \
--name web \
--network my-overlay \
--replicas 3 \
nginx:alpine5.2 Overlay 网络加密
bash
# 创建加密的 Overlay 网络
docker network create \
--driver overlay \
--opt encrypted \
--subnet 10.0.0.0/16 \
secure-overlay5.3 Overlay 网络架构
┌─────────────────────┐ ┌─────────────────────┐
│ Docker Host 1 │ │ Docker Host 2 │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ Container │ │ │ │ Container │ │
│ │ 10.0.0.2 │ │◄───────►│ │ 10.0.0.3 │ │
│ └───────┬───────┘ │ VXLAN │ └───────┬───────┘ │
│ │ │ Tunnel │ │ │
│ ┌───────▼───────┐ │ │ ┌───────▼───────┐ │
│ │ VXLAN │ │◄───────►│ │ VXLAN │ │
│ │ Interface │ │ │ │ Interface │ │
│ └───────────────┘ │ │ └───────────────┘ │
└─────────────────────┘ └─────────────────────┘端口映射
6.1 基本端口映射
bash
# 映射单个端口
docker run -d -p 8080:80 nginx:alpine
# 映射多个端口
docker run -d \
-p 8080:80 \
-p 8443:443 \
nginx:alpine
# 映射到随机主机端口
docker run -d -p 80 nginx:alpine
# 查看映射的端口
docker port <container-id>6.2 高级端口映射
bash
# 指定绑定地址
docker run -d -p 127.0.0.1:8080:80 nginx:alpine
# 指定协议
docker run -d -p 8080:80/udp nginx:alpine
# 映射端口范围
docker run -d -p 8000-8010:8000-8010 nginx:alpine
# 使用主机网络接口
docker run -d -p 192.168.1.100:8080:80 nginx:alpine6.3 端口映射与防火墙
bash
# 查看 Docker 创建的 iptables 规则
iptables -t nat -L DOCKER -n -v
# 查看端口转发规则
iptables -t nat -L PREROUTING -n -v | grep DOCKER自定义网络
7.1 创建高级网络配置
bash
# 创建具有完整配置的网络
docker network create \
--driver bridge \
--subnet 192.168.100.0/24 \
--gateway 192.168.100.1 \
--ip-range 192.168.100.128/25 \
--ipv6 \
--subnet fd00:dead:beef::/48 \
--label environment=production \
--label project=myapp \
--opt com.docker.network.bridge.name=br-custom \
--opt com.docker.network.bridge.enable_icc=true \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
--opt com.docker.network.driver.mtu=1450 \
custom-network7.2 网络配置选项
| 选项 | 说明 | 默认值 |
|---|---|---|
--subnet | 子网 CIDR | 自动分配 |
--gateway | 网关 IP | 子网第一个地址 |
--ip-range | IP 分配范围 | 整个子网 |
--aux-address | 排除的 IP | 无 |
--opt encrypted | 加密流量 | false |
--attachable | 允许非 Swarm 容器连接 | false |
7.3 网络管理命令
bash
# 列出所有网络
docker network ls
# 查看网络详情
docker network inspect network-name
# 连接容器到网络
docker network connect network-name container-name
# 断开容器网络连接
docker network disconnect network-name container-name
# 删除网络
docker network rm network-name
# 清理未使用的网络
docker network prune容器 DNS 配置
8.1 默认 DNS 行为
Docker 使用嵌入式 DNS 服务器(127.0.0.11)为容器提供名称解析。
bash
# 查看容器的 DNS 配置
docker run --rm alpine cat /etc/resolv.conf
# 输出示例:
# nameserver 127.0.0.118.2 自定义 DNS 配置
bash
# 指定 DNS 服务器
docker run -d \
--dns 8.8.8.8 \
--dns 8.8.4.4 \
--dns-search example.com \
--dns-opt ndots:2 \
nginx:alpine8.3 Docker Compose DNS 配置
yaml
version: '3.8'
services:
web:
image: nginx:alpine
dns:
- 8.8.8.8
- 8.8.4.4
dns_search:
- example.com
dns_opt:
- ndots:2
- timeout:2
extra_hosts:
- "database:192.168.1.100"
- "cache:192.168.1.101"8.4 服务发现
在自定义网络中,容器可以通过名称相互发现:
bash
# 创建网络
docker network create my-app
# 运行服务
docker run -d --name api --network my-app myapi:latest
docker run -d --name web --network my-app myweb:latest
# 在 web 容器中可以解析 api 名称
docker exec web nslookup api网络安全
9.1 网络隔离
bash
# 禁用容器间通信
docker network create \
--opt com.docker.network.bridge.enable_icc=false \
isolated-network
# 禁用 IP 伪装(容器无法访问外部网络)
docker network create \
--opt com.docker.network.bridge.enable_ip_masquerade=false \
internal-network9.2 防火墙规则
bash
# 查看 Docker 创建的规则
iptables -L DOCKER-ISOLATION-STAGE-1 -n -v
iptables -L DOCKER-ISOLATION-STAGE-2 -n -v
# 自定义容器防火墙规则
docker run -d \
--cap-add NET_ADMIN \
--security-opt seccomp=unconfined \
myapp:latest9.3 网络策略(Swarm)
yaml
version: '3.8'
services:
frontend:
image: nginx:alpine
networks:
- frontend-network
deploy:
placement:
constraints:
- node.role == worker
backend:
image: myapi:latest
networks:
- frontend-network
- backend-network
deploy:
placement:
constraints:
- node.role == worker
database:
image: postgres:15-alpine
networks:
- backend-network
deploy:
placement:
constraints:
- node.role == manager
networks:
frontend-network:
driver: overlay
internal: false
backend-network:
driver: overlay
internal: true # 无外部访问故障排查
10.1 网络诊断工具
bash
# 使用 netshoot 进行网络诊断
docker run --rm --network container:target-container \
nicolaka/netshoot \
tcpdump -i eth0
# 常用诊断命令
docker run --rm --network container:target nicolaka/netshoot dig google.com
docker run --rm --network container:target nicolaka/netshoot traceroute 8.8.8.8
docker run --rm --network container:target nicolaka/netshoot curl -v http://service10.2 常见问题
bash
# 容器无法访问外部网络
# 检查 IP 转发
sysctl net.ipv4.ip_forward
# 检查 NAT 规则
iptables -t nat -L POSTROUTING -n -v
# 容器间无法通信
# 检查是否在同一网络
docker inspect container1 --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
docker inspect container2 --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
# DNS 解析失败
# 检查 DNS 配置
docker run --rm alpine nslookup google.com
docker run --rm --dns 8.8.8.8 alpine nslookup google.com10.3 网络重置
bash
# 停止 Docker
systemctl stop docker
# 清理网络配置
iptables -t nat -F
iptables -F DOCKER
ip link del docker0
# 重启 Docker
systemctl start docker