Docker 网络配置
本章将深入讲解 Docker 网络的配置和管理,包括网络模式、自定义网络、服务发现、负载均衡等核心概念和实践。
Docker 网络概述
网络架构
Docker 网络基于 Linux 网络命名空间技术,为容器提供网络隔离和通信能力:
┌─────────────────────────────────────────────────────────┐
│ 主机网络 │
├─────────────────────────────────────────────────────────┤
│ Docker 网络层 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ bridge │ │ host │ │ none │ │
│ │ 网络 │ │ 网络 │ │ 网络 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 容器网络命名空间 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 容器 A │ │ 容器 B │ │ 容器 C │ │
│ │ eth0 │ │ eth0 │ │ (无网络) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘网络驱动类型
| 驱动类型 | 描述 | 使用场景 |
|---|---|---|
| bridge | 默认网络驱动,创建虚拟网桥 | 单主机容器通信 |
| host | 容器直接使用主机网络 | 高性能网络需求 |
| none | 禁用容器网络 | 安全隔离场景 |
| overlay | 跨主机容器通信 | 集群和 Swarm 模式 |
| macvlan | 为容器分配 MAC 地址 | 需要直接连接物理网络 |
网络基础操作
网络管理命令
bash
# 列出所有网络
docker network ls
# 查看网络详细信息
docker network inspect bridge
# 创建自定义网络
docker network create mynetwork
# 删除网络
docker network rm mynetwork
# 清理未使用的网络
docker network prune
# 连接容器到网络
docker network connect mynetwork container_name
# 断开容器网络连接
docker network disconnect mynetwork container_name查看容器网络信息
bash
# 查看容器网络配置
docker inspect container_name | grep -A 20 "NetworkSettings"
# 查看容器 IP 地址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name
# 查看容器端口映射
docker port container_name
# 在容器内查看网络配置
docker exec container_name ip addr show
docker exec container_name netstat -tulpnBridge 网络
默认 Bridge 网络
bash
# 运行容器使用默认 bridge 网络
docker run -d --name web1 nginx
docker run -d --name web2 nginx
# 查看默认网络
docker network inspect bridge
# 容器间通信(通过 IP 地址)
docker exec web1 ping $(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web2)自定义 Bridge 网络
bash
# 创建自定义 bridge 网络
docker network create --driver bridge mybridge
# 指定子网和网关
docker network create \
--driver bridge \
--subnet=172.20.0.0/16 \
--ip-range=172.20.240.0/20 \
--gateway=172.20.0.1 \
mybridge
# 在自定义网络中运行容器
docker run -d --name web1 --network mybridge nginx
docker run -d --name web2 --network mybridge nginx
# 容器间通信(通过容器名)
docker exec web1 ping web2Bridge 网络配置选项
bash
# 创建带配置的 bridge 网络
docker network create \
--driver bridge \
--subnet=192.168.100.0/24 \
--gateway=192.168.100.1 \
--ip-range=192.168.100.128/25 \
--opt com.docker.network.bridge.name=mybr0 \
--opt com.docker.network.bridge.enable_icc=true \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
--opt com.docker.network.driver.mtu=1500 \
advanced-bridge
# 指定容器 IP 地址
docker run -d --name web \
--network advanced-bridge \
--ip 192.168.100.10 \
nginxHost 网络
Host 网络使用
bash
# 使用主机网络
docker run -d --name web --network host nginx
# 查看容器网络(与主机相同)
docker exec web ip addr show
# 直接访问主机端口
curl http://localhost:80Host 网络特点
优势:
- 网络性能最佳,无 NAT 开销
- 容器可以直接绑定主机端口
- 适合高性能网络应用
劣势:
- 容器与主机共享网络命名空间
- 端口冲突风险
- 安全性较低
bash
# 示例:高性能数据库
docker run -d \
--name postgres \
--network host \
-e POSTGRES_PASSWORD=password \
postgres:13
# 直接连接到主机的 5432 端口
psql -h localhost -U postgresNone 网络
禁用网络
bash
# 创建无网络容器
docker run -d --name isolated --network none alpine sleep 3600
# 查看网络配置(只有 loopback)
docker exec isolated ip addr show
# 手动配置网络(如果需要)
docker exec isolated ip link add eth0 type dummy应用场景
bash
# 安全处理敏感数据
docker run --rm -it \
--network none \
--volume /host/data:/data:ro \
my-secure-processor
# 离线数据处理
docker run --rm \
--network none \
--volume /input:/input:ro \
--volume /output:/output \
data-processor自定义网络
创建多网络架构
bash
# 创建前端网络
docker network create frontend
# 创建后端网络
docker network create backend
# 创建数据库网络
docker network create database
# Web 服务器(连接前端和后端)
docker run -d --name web \
--network frontend \
nginx
docker network connect backend web
# API 服务器(连接后端和数据库)
docker run -d --name api \
--network backend \
myapi
docker network connect database api
# 数据库(只连接数据库网络)
docker run -d --name db \
--network database \
postgres网络别名
bash
# 创建网络
docker network create mynetwork
# 使用网络别名
docker run -d --name web1 \
--network mynetwork \
--network-alias web \
nginx
docker run -d --name web2 \
--network mynetwork \
--network-alias web \
nginx
# 通过别名访问(负载均衡)
docker run --rm --network mynetwork alpine \
nslookup web端口映射
基本端口映射
bash
# 映射单个端口
docker run -d -p 8080:80 --name web nginx
# 映射多个端口
docker run -d -p 8080:80 -p 8443:443 --name web nginx
# 映射到指定 IP
docker run -d -p 127.0.0.1:8080:80 --name web nginx
# 映射 UDP 端口
docker run -d -p 8080:80/udp --name app myapp
# 映射端口范围
docker run -d -p 8000-8010:8000-8010 --name app myapp
# 映射到随机端口
docker run -d -P --name web nginx动态端口映射
bash
# 查看映射的随机端口
docker port web 80
# 获取端口号用于脚本
PORT=$(docker port web 80 | cut -d: -f2)
echo "Web server is running on port $PORT"
# 使用环境变量
docker run -d -p ${HOST_PORT:-8080}:80 --name web nginx容器间通信
同网络容器通信
bash
# 创建应用网络
docker network create app-network
# 运行数据库
docker run -d --name database \
--network app-network \
-e POSTGRES_PASSWORD=password \
postgres:13
# 运行应用(通过容器名连接数据库)
docker run -d --name webapp \
--network app-network \
-e DATABASE_URL=postgresql://postgres:password@database:5432/mydb \
mywebapp
# 测试连接
docker exec webapp ping database跨网络容器通信
bash
# 创建多个网络
docker network create frontend
docker network create backend
# API 网关连接两个网络
docker run -d --name gateway \
--network frontend \
nginx
docker network connect backend gateway
# 前端服务
docker run -d --name frontend-app \
--network frontend \
my-frontend
# 后端服务
docker run -d --name backend-app \
--network backend \
my-backend服务发现
DNS 服务发现
bash
# 创建网络
docker network create service-network
# 运行服务
docker run -d --name service1 \
--network service-network \
--hostname service1.local \
myservice
docker run -d --name service2 \
--network service-network \
--hostname service2.local \
myservice
# DNS 查询
docker run --rm --network service-network alpine \
nslookup service1
docker run --rm --network service-network alpine \
dig service1.local使用 Consul 服务发现
yaml
# docker-compose.yml
version: '3.8'
services:
consul:
image: consul:latest
ports:
- "8500:8500"
command: agent -server -bootstrap -ui -client=0.0.0.0
networks:
- service-network
service1:
image: myservice
depends_on:
- consul
environment:
- CONSUL_URL=http://consul:8500
- SERVICE_NAME=service1
networks:
- service-network
service2:
image: myservice
depends_on:
- consul
environment:
- CONSUL_URL=http://consul:8500
- SERVICE_NAME=service2
networks:
- service-network
networks:
service-network:
driver: bridge负载均衡
Nginx 负载均衡
nginx
# nginx.conf
upstream backend {
server backend1:8080;
server backend2:8080;
server backend3:8080;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}yaml
# docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- backend1
- backend2
- backend3
networks:
- app-network
backend1:
image: mybackend
networks:
- app-network
backend2:
image: mybackend
networks:
- app-network
backend3:
image: mybackend
networks:
- app-network
networks:
app-network:
driver: bridgeHAProxy 负载均衡
# haproxy.cfg
global
daemon
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend web_frontend
bind *:80
default_backend web_servers
backend web_servers
balance roundrobin
server web1 web1:80 check
server web2 web2:80 check
server web3 web3:80 check网络安全
网络隔离
bash
# 创建隔离的内部网络
docker network create --internal backend-network
# 只有后端服务可以访问数据库
docker run -d --name database \
--network backend-network \
postgres
docker run -d --name api \
--network backend-network \
myapi
# 前端无法直接访问数据库
docker run -d --name frontend \
--network frontend-network \
myfrontend防火墙规则
bash
# 限制容器网络访问
iptables -I DOCKER-USER -s 172.17.0.0/16 -d 192.168.1.0/24 -j DROP
# 允许特定端口
iptables -I DOCKER-USER -p tcp --dport 80 -j ACCEPT
iptables -I DOCKER-USER -p tcp --dport 443 -j ACCEPT
# 限制容器间通信
iptables -I DOCKER-USER -i docker0 -o docker0 -j DROP网络加密
yaml
# 使用 TLS 加密的服务
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./ssl:/etc/nginx/ssl:ro
- ./nginx-ssl.conf:/etc/nginx/nginx.conf:ro
networks:
- secure-network
app:
image: myapp
environment:
- TLS_CERT_FILE=/certs/cert.pem
- TLS_KEY_FILE=/certs/key.pem
volumes:
- ./certs:/certs:ro
networks:
- secure-network
networks:
secure-network:
driver: bridge
driver_opts:
encrypted: "true"网络监控
网络流量监控
bash
# 监控容器网络流量
docker exec container_name netstat -i
# 使用 iftop 监控
docker exec -it container_name iftop
# 监控网络连接
docker exec container_name ss -tulpn
# 网络性能测试
docker run --rm --network mynetwork alpine \
sh -c "apk add --no-cache iperf3 && iperf3 -c target_container"网络诊断工具
bash
# 网络连通性测试
docker run --rm --network mynetwork alpine ping target_container
# DNS 解析测试
docker run --rm --network mynetwork alpine nslookup target_container
# 端口连通性测试
docker run --rm --network mynetwork alpine \
sh -c "apk add --no-cache netcat-openbsd && nc -zv target_container 80"
# 路由跟踪
docker run --rm --network mynetwork alpine traceroute target_container高级网络配置
Macvlan 网络
bash
# 创建 macvlan 网络
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
macvlan-network
# 运行容器获得独立 MAC 地址
docker run -d --name web \
--network macvlan-network \
--ip 192.168.1.100 \
nginxOverlay 网络(Swarm 模式)
bash
# 初始化 Swarm
docker swarm init
# 创建 overlay 网络
docker network create --driver overlay --attachable myoverlay
# 跨节点容器通信
docker run -d --name web1 --network myoverlay nginx
docker run -d --name web2 --network myoverlay nginx
# 在不同节点上的容器可以直接通信自定义网络驱动
bash
# 安装第三方网络插件
docker plugin install store/weaveworks/net-plugin:latest
# 使用自定义驱动创建网络
docker network create --driver weave myweave
# 运行容器
docker run -d --network myweave nginx故障排查
网络问题诊断
bash
# 检查网络配置
docker network ls
docker network inspect network_name
# 检查容器网络
docker inspect container_name | grep -A 20 "NetworkSettings"
# 测试网络连通性
docker exec container1 ping container2
# 检查端口监听
docker exec container_name netstat -tulpn
# 查看路由表
docker exec container_name ip route show
# 检查 iptables 规则
sudo iptables -L DOCKER-USER
sudo iptables -L DOCKER常见问题解决
bash
# 问题 1: 容器无法访问外网
# 检查 DNS 配置
docker exec container_name cat /etc/resolv.conf
# 重启 Docker 服务
sudo systemctl restart docker
# 问题 2: 端口映射不生效
# 检查防火墙规则
sudo ufw status
sudo iptables -L
# 问题 3: 容器间无法通信
# 检查网络连接
docker network inspect network_name
# 重新连接网络
docker network disconnect network_name container_name
docker network connect network_name container_name性能优化
网络性能调优
bash
# 调整网络缓冲区大小
echo 'net.core.rmem_max = 134217728' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 134217728' >> /etc/sysctl.conf
# 优化 TCP 参数
echo 'net.ipv4.tcp_congestion_control = bbr' >> /etc/sysctl.conf
# 应用配置
sysctl -p容器网络优化
bash
# 使用 host 网络提高性能
docker run -d --network host high-performance-app
# 调整 MTU 大小
docker network create --driver bridge \
--opt com.docker.network.driver.mtu=9000 \
jumbo-network
# 禁用不必要的网络功能
docker run -d \
--sysctl net.ipv6.conf.all.disable_ipv6=1 \
myapp本章小结
本章全面介绍了 Docker 网络配置的各个方面:
关键要点:
- 网络模式:bridge、host、none、overlay 等不同模式
- 自定义网络:创建隔离的网络环境
- 服务发现:容器间通过名称通信
- 负载均衡:分发流量到多个容器
- 网络安全:隔离和加密网络通信
- 监控诊断:网络问题排查和性能优化
最佳实践:
- 使用自定义网络而不是默认 bridge
- 合理设计网络架构和隔离策略
- 实施适当的安全措施
- 监控网络性能和流量
- 定期检查和优化网络配置
在下一章中,我们将学习 Docker 的故障排查,包括常见问题诊断和解决方案。