08-网络管理-让容器之间互相通信
容器之间怎么通信?
问题:默认情况下,容器之间是隔离的,无法直接访问。
场景:
- Web应用容器需要访问数据库容器
- 多个微服务容器需要互相调用
- 外部需要访问容器内的服务
解决:使用Docker网络实现容器间通信。
Docker网络基础
网络类型
1. bridge(桥接网络,默认)
特点:
- 默认网络类型
- 每个容器分配独立IP
- 容器通过bridge互相通信
- 通过端口映射对外暴露服务
原理:
宿主机
│
├── docker0(虚拟网桥)
│ │
│ ├── 容器A (172.17.0.2)
│ ├── 容器B (172.17.0.3)
│ └── 容器C (172.17.0.4)
2. host(主机网络)
特点:
- 容器使用宿主机网络栈
- 没有网络隔离
- 性能最好
- 不需要端口映射
使用场景:
- 高性能应用
- 需要直接访问宿主机网络
docker run --network=host nginx
3. none(无网络)
特点:
- 容器没有网络
- 完全隔离
- 适合不需要网络的应用
docker run --network=none alpine sleep 3600
4. overlay(覆盖网络)
特点:
- 跨主机容器通信
- 需要Swarm或Kubernetes
- 生产环境常用
使用场景:
- 分布式应用
- 微服务架构
网络基本操作
1. 查看网络
# 列出所有网络
docker network ls
# 查看网络详细信息
docker network inspect bridge
# 查看网络中的容器
docker network inspect bridge | grep -A 10 Containers
输出示例:
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
abc123def456 host host local
123abc456def none null local
2. 创建网络
# 创建bridge网络
docker network create my-network
# 创建自定义bridge网络(指定子网)
docker network create \
--driver=bridge \
--subnet=172.20.0.0/16 \
--ip-range=172.20.10.0/24 \
--gateway=172.20.10.1 \
my-custom-network
# 创建overlay网络(Swarm集群)
docker network create --driver=overlay my-overlay-network
3. 删除网络
# 删除网络
docker network rm my-network
# 删除未使用的网络
docker network prune
4. 连接容器到网络
# 运行容器时指定网络
docker run -d --network=bridge --name myapp nginx
# 将已有容器连接到网络
docker network connect my-network myapp
# 断开容器与网络的连接
docker network disconnect my-network myapp
# 连接时指定别名
docker network connect --alias web my-network myapp
容器间通信
场景1:同一网络中的容器通信
# 1. 创建网络
docker network create app-network
# 2. 运行Web应用容器
docker run -d \
--network=app-network \
--name webapp \
nginx
# 3. 运行数据库容器
docker run -d \
--network=app-network \
--name db \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 4. Web应用可以直接通过名称访问数据库
docker exec webapp ping db
docker exec webapp nc -zv db 3306
关键点:
- 同一网络中的容器可以通过容器名称互相访问
- Docker内置DNS自动解析容器名称
场景2:跨网络容器通信
# 1. 创建两个网络
docker network create frontend-network
docker network create backend-network
# 2. 前端容器连接到前端网络
docker run -d \
--network=frontend-network \
--name frontend \
nginx
# 3. 后端容器同时连接到前后端网络
docker run -d \
--name backend \
--network=backend-network \
nginx
# 4. 将后端也连接到前端网络
docker network connect frontend-network backend
# 5. 前端可以访问后端
docker exec frontend ping backend
场景3:固定IP地址
# 创建自定义子网
docker network create \
--subnet=172.20.0.0/16 \
--ip-range=172.20.10.0/24 \
--gateway=172.20.10.1 \
my-network
# 运行容器时指定IP
docker run -d \
--network=my-network \
--ip=172.20.10.100 \
--name myapp \
nginx
# 验证IP
docker inspect myapp | grep IPAddress
端口映射
基本端口映射
# 映射容器端口到宿主机
docker run -d -p 80:80 --name web nginx
# 映射多个端口
docker run -d -p 80:80 -p 443:443 --name web nginx
# 映射到随机端口
docker run -d -P --name web nginx
# 查看随机分配的端口
docker port web
绑定到特定地址
# 只绑定到localhost(只允许本地访问)
docker run -d -p 127.0.0.1:80:80 --name web nginx
# 绑定到所有接口(默认)
docker run -d -p 0.0.0.0:80:80 --name web nginx
# 绑定到特定IP
docker run -d -p 192.168.1.100:80:80 --name web nginx
端口范围映射
# 映射端口范围
docker run -d -p 8000-8010:8000-8010 --name web nginx
实战:完整的多容器应用
架构
┌─────────────────────────────────────────────────────┐
│ 宿主机 │
│ ┌───────────────────────────────────────────────┐ │
│ │ app-network(自定义网络) │ │
│ │ │ │
│ │ ┌────────────┐ ┌────────────┐ │ │
│ │ │ Web容器 │─────>│ DB容器 │ │ │
│ │ │ (nginx) │ │ (mysql) │ │ │
│ │ └────────────┘ └────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────┘ │
│ │
│ 端口映射:8080 -> Web容器80 │
└─────────────────────────────────────────────────────┘
完整步骤
# 1. 创建网络
docker network create app-network
# 2. 运行MySQL容器
docker run -d \
--name db \
--network=app-network \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=mydb \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# 3. 等待MySQL启动
sleep 20
# 4. 创建测试数据
docker exec db mysql -uroot -p123456 -e \
"USE mydb; CREATE TABLE users (id INT, name VARCHAR(100)); INSERT INTO users VALUES (1, 'Alice');"
# 5. 运行Web容器
docker run -d \
--name web \
--network=app-network \
-p 8080:80 \
nginx
# 6. 验证网络连通性
docker exec web ping db
docker exec web nc -zv db 3306
# 7. 访问Web应用
curl http://localhost:8080
网络排错
1. 检查网络连接
# 检查容器是否在同一网络
docker inspect web | grep -A 10 Networks
docker inspect db | grep -A 10 Networks
2. 测试网络连通性
# ping测试
docker exec web ping db
# 端口测试
docker exec web nc -zv db 3306
# DNS解析
docker exec web nslookup db
3. 查看网络日志
# 查看容器网络接口
docker exec web ip addr
# 查看路由表
docker exec web ip route
# 查看网络统计
docker exec web netstat -tuln
4. 抓包分析
# 安装tcpdump(需要基础镜像支持)
docker exec web apt-get update && apt-get install -y tcpdump
# 抓包
docker exec web tcpdump -i eth0
网络性能优化
1. 使用host网络(无NAT开销)
# 高性能场景
docker run --network=host nginx
2. 减少网络跳数
# 直接连接,避免多层NAT
docker network create --driver=bridge my-network
3. 使用DNS缓存
# 使用--dns选项
docker run --dns=8.8.8.8 --dns=114.114.114.114 nginx
安全考虑
1. 隔离不同环境的网络
# 开发环境
docker network create dev-network
# 测试环境
docker network create test-network
# 生产环境
docker network create prod-network
2. 限制网络访问
# 只允许特定网络访问
docker run --network=none app
# 然后只连接到必要的网络
docker network connect app-network app
3. 使用加密通信
# 使用TLS加密的overlay网络(Swarm)
docker network create --driver=overlay --opt encrypted my-encrypted-network
本章小结
- 网络类型:bridge(桥接)、host(主机)、none(无网络)、overlay(覆盖)
- 网络操作:创建、查看、删除网络
- 容器通信:同一网络通过容器名称访问,跨网络需要连接
- 端口映射:映射容器端口到宿主机
- 网络排错:检查连通性、DNS解析、抓包分析
现在已经掌握了网络管理,下一章我们来学习Docker Compose!
继续学下去,马上就能一键启动复杂项目了!