在前两章掌握网络基础与进阶能力后,本章聚焦实战:复杂网络拓扑设计、服务发现与DNS、负载均衡、网络监控与安全策略。
17.1 复杂网络拓扑设计
17.1.1 三层网络拓扑
text
三层拓扑(前端 / 应用 / 数据库):
Internet
│
┌──▼──┐
│Nginx│ (public网络)
└──┬──┘
│
┌──▼──┐
│ API │ (public + private网络)
└──┬──┘
│
┌──▼──┐
│ DB │ (private网络)
└─────┘
访问关系:Internet -> Nginx -> API -> DB
yaml
# docker-compose.yml
version: '3.8'
networks:
public:
private:
internal: true
services:
nginx:
image: nginx:alpine
networks:
- public
ports:
- "80:80"
depends_on:
- api
api:
image: myapi
networks:
- public
- private
environment:
- DB_HOST=db
db:
image: postgres:13
networks:
- private
volumes:
- db-data:/var/lib/postgresql/data
volumes:
db-data:
17.1.2 双网卡容器(接入多个网络)
bash
# 创建两个网络
docker network create frontend-net
docker network create backend-net
# 启动容器并加入frontend网络
docker run -d --name api --network frontend-net myapi
# 再连接到backend网络
docker network connect backend-net api
# 查看容器IP
# docker inspect api -f '{{json .NetworkSettings.Networks}}'
适用场景:API网关、双向代理、应用层安全隔离。
17.1.3 仅内部可访问的网络
bash
# 创建internal网络(无外网访问)
docker network create --internal internal-net
# 仅内部服务加入
docker run -d --name db --network internal-net postgres
# 其他服务也需加入内部网络才能访问
docker run -d --name api --network internal-net myapi
17.2 服务发现与DNS
17.2.1 Docker内置DNS
Docker自定义网络默认启用内置DNS(127.0.0.11)。
bash
# 创建网络
docker network create app-net
# 启动容器
docker run -d --name api --network app-net myapi
docker run -d --name web --network app-net nginx
# 容器内通过服务名访问
# curl http://api:8080
17.2.2 网络别名(Service Alias)
bash
# 使用网络别名
docker run -d \
--name api-v1 \
--network app-net \
--network-alias api \
myapi:v1
docker run -d \
--name api-v2 \
--network app-net \
--network-alias api \
myapi:v2
# 访问 api 触发轮询解析
# nslookup api
17.2.3 自定义DNS服务器
bash
# 运行时指定DNS
docker run -d \
--dns 10.10.0.2 \
--dns-search example.local \
nginx
# daemon级别配置 /etc/docker/daemon.json
{
"dns": ["10.10.0.2", "8.8.8.8"],
"dns-search": ["example.local"]
}
17.3 负载均衡与服务暴露
17.3.1 Docker内置轮询解析
自定义网络中,同一别名会解析到多个IP,实现简单轮询。
bash
# 创建3个副本
for i in 1 2 3; do
docker run -d --name api-$i --network app-net --network-alias api myapi
done
# 在容器内测试
# nslookup api
# 结果返回多个IP
17.3.2 Nginx反向代理负载均衡
nginx
# nginx.conf
upstream backend {
server api-1:8080;
server api-2:8080;
server api-3:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
bash
# 启动Nginx并挂载配置
docker run -d \
--name gateway \
--network app-net \
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
-p 80:80 \
nginx
17.3.3 Swarm服务负载均衡
bash
# 创建Swarm服务(内置负载均衡)
docker service create \
--name api \
--replicas 3 \
--network my-overlay \
myapi
# 服务VIP自动负载均衡
# 访问 api 即可
17.4 网络监控与可观测性
17.4.1 监控指标
- 容器网络吞吐量(rx/tx bytes)
- 连接数(ESTABLISHED)
- DNS解析失败率
- 端口可达性
17.4.2 快速监控脚本
bash
#!/bin/bash
# docker-net-stats.sh
printf "%-20s %-12s %-12s\n" "CONTAINER" "RX" "TX"
for c in $(docker ps -q); do
name=$(docker inspect $c -f '{{.Name}}' | sed 's/\///')
stats=$(docker exec $c cat /proc/net/dev | awk '/eth0/ {print $2" "$10}')
rx=$(echo $stats | awk '{print $1}')
tx=$(echo $stats | awk '{print $2}')
printf "%-20s %-12s %-12s\n" "$name" "$rx" "$tx"
done
17.4.3 Netshoot诊断容器
bash
# 进入目标容器网络空间进行诊断
docker run -it --rm \
--network container:mycontainer \
nicolaka/netshoot
# 常用命令:
# ping, dig, traceroute, tcpdump, ss, netstat
17.4.4 Prometheus + cAdvisor(可选)
yaml
# 简化监控栈(示例)
version: '3.8'
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
17.5 网络安全策略
17.5.1 最小暴露原则
bash
# 仅绑定到本地
docker run -d -p 127.0.0.1:8080:80 nginx
# 仅开放必要端口
docker run -d -p 80:80 nginx
17.5.2 DOCKER-USER防火墙策略
bash
# 默认策略:限制特定网段访问
sudo iptables -I DOCKER-USER -s 10.0.0.0/8 -j DROP
# 允许特定容器访问外部服务
CONTAINER_IP=$(docker inspect api -f '{{.NetworkSettings.IPAddress}}')
sudo iptables -I DOCKER-USER -s $CONTAINER_IP -d 10.0.0.5 -j ACCEPT
17.5.3 网络隔离建议
text
✅ 前端与数据库隔离(public/private)
✅ 仅API服务同时加入两个网络
✅ 使用internal网络屏蔽外网访问
✅ 关键服务不使用host模式
17.6 常见问题排查流程
17.6.1 排查清单
text
1. 容器在同一网络?
2. DNS解析是否正确?
3. 是否有端口映射冲突?
4. 服务端口是否监听?
5. 防火墙/iptables是否拦截?
6. 主机IP转发是否开启?
17.6.2 诊断脚本(完整版)
bash
#!/bin/bash
# net-triage.sh
CONTAINER=$1
if [ -z "$CONTAINER" ]; then
echo "Usage: $0 <container>"
exit 1
fi
echo "=== Network Triage for $CONTAINER ==="
echo "1) Network:"
docker inspect $CONTAINER --format '{{json .NetworkSettings.Networks}}' | jq
echo -e "\n2) DNS:"
docker exec $CONTAINER cat /etc/resolv.conf
echo -e "\n3) Routes:"
docker exec $CONTAINER ip route
echo -e "\n4) Ping gateway:"
GW=$(docker exec $CONTAINER ip route | awk '/default/ {print $3}')
docker exec $CONTAINER ping -c 2 $GW
echo -e "\n5) DNS lookup:"
docker exec $CONTAINER nslookup google.com
echo -e "\n6) Internet ping:"
docker exec $CONTAINER ping -c 2 8.8.8.8
echo -e "\n7) Host iptables (docker):"
sudo iptables -t nat -L -n | grep docker
17.7 实战:完整网络架构示例
17.7.1 电商系统网络拓扑
text
Internet
│
▼
Nginx (public)
│
▼
API Gateway (public + private)
│
▼
Service Mesh (private)
│
▼
DB/Cache (private + internal)
yaml
version: '3.8'
networks:
public:
private:
internal:
internal: true
services:
nginx:
image: nginx:alpine
networks:
- public
ports:
- "80:80"
gateway:
image: my-gateway
networks:
- public
- private
user-service:
image: user-service
networks:
- private
order-service:
image: order-service
networks:
- private
db:
image: postgres
networks:
- internal
volumes:
- db-data:/var/lib/postgresql/data
redis:
image: redis
networks:
- internal
volumes:
db-data:
17.8 小结
通过本章学习,你已经具备了Docker网络实战能力:
✅ 复杂网络拓扑设计
- 三层网络设计
- 多网络连接
- internal网络隔离
✅ 服务发现与DNS
- 内置DNS机制
- 网络别名与轮询
- 自定义DNS配置
✅ 负载均衡
- 内置轮询解析
- Nginx反向代理
- Swarm服务负载均衡
✅ 网络监控与排查
- 监控指标
- Netshoot诊断
- 排查脚本
✅ 安全策略
- 最小暴露原则
- DOCKER-USER防火墙
- 网络隔离建议
下一步
在第18章中,我们将学习Docker Compose基础:
- Compose是什么
- docker-compose.yml结构
- 常用命令
- 单机多容器编排
本章思考题:
- 如何设计一个三层安全网络?
- Docker内置DNS的工作机制是什么?
- 为什么要使用DOCKER-USER链?
- Swarm的负载均衡和Nginx负载均衡有什么区别?
- 如何快速定位容器网络问题?
相关资源:
- Docker网络实践:https://docs.docker.com/network/
- Netshoot工具:https://github.com/nicolaka/netshoot
- Docker防火墙:https://docs.docker.com/network/iptables/