容器间通信方式
面试题
Docker 容器之间有哪些通信方式?各有什么优缺点?
标准答案
容器间通信是微服务架构的基础需求。Docker 提供了多种通信方式,从简单到复杂,各有适用场景。
通信方式概览
| 方式 | 原理 | 复杂度 | 推荐场景 |
|---|---|---|---|
| 默认 bridge IP 通信 | 通过 IP 地址互访 | 低 | 简单测试 |
| 自定义 bridge DNS | 通过容器名自动解析 | 低 | 生产首选 |
| –link 传统方式 | 手动建立连接 | 低 | 已废弃,不推荐 |
| 共享网络命名空间 | 网络模式设为 container | 中 | 极特殊场景 |
| 端口暴露 | 通过宿主机端口互通 | 中 | 跨宿主机场景 |
| host 模式 | 共享宿主机网络 | 低 | 性能敏感场景 |
方式一:默认 bridge IP 通信
# 默认 bridge 模式下
docker run -d --name web1 nginx
docker run -d --name web2 nginx
# 可以用 IP 通信
docker exec web1 curl http://172.17.0.3
# 但❌不能用容器名通信
docker exec web1 curl http://web2
# curl: (6) Could not resolve host: web2
缺点:
– IP 地址不固定(容器重启 IP 可能变化)
– 不能通过容器名解析
– 不适合生产环境
方式二:自定义 bridge 网络(推荐)
# 1. 创建自定义 bridge 网络
docker network create --driver bridge mynet
# 2. 将容器连接到同一个网络
docker run -d --name web --network mynet nginx
docker run -d --name api --network mynet myapi:latest
# 3. ✅ 容器名互相通信(自动 DNS 解析)
docker exec web curl http://api:3000
docker exec api curl http://web:80
# 4. 将一个已有容器加入到网络
docker network connect mynet existing-container
优点:
– 支持自动 DNS 解析(容器名 → IP)
– IP 变化不影响通信
– 网络间的隔离性更好
– 可以随时加入/离开网络
最佳实践:
# docker-compose.yml
# 默认创建自定义 bridge 网络
services:
web:
image: nginx:alpine
networks:
- frontend
api:
image: myapi:latest
networks:
- frontend
- backend
db:
image: postgres:15
networks:
- backend
networks:
frontend:
backend:
方式三:–link(传统/已废弃)
# 老版本 Docker 的通信方式
docker run -d --name db postgres:15
docker run -d --name web --link db:db nginx
# 可以 ping 通 db 容器名
docker exec web ping db
为什么不推荐:
– 官方文档已标注为 Legacy(遗留特性)
– 只能在同一个宿主机工作
– 功能有局限性
– 自定义 bridge 完全替代了它
方式四:共享网络命名空间
# 容器 B 共享容器 A 的网络
docker run -d --name container-a alpine sleep 3600
docker run -d --name container-b --network container:container-a alpine sleep 3600
# container-b 和 container-a 共享同一个 IP 和端口空间
docker exec container-b ip addr
# 可以看到 container-a 的网卡信息
# 通过 localhost 通信
docker exec container-b curl http://localhost:PORT
# 如果 container-a 有服务在运行,container-b 可以直接通过 localhost 访问
适用场景:
– sidecar 模式(日志收集器、监控代理)
– 需要高性能 IPC 的场景
– 网络配置继承(比如两个容器需要同一个 IP)
方式五:通过宿主机端口
docker run -d -p 8080:80 --name web nginx
docker run -d --name client alpine
# 通过宿主机 IP + 映射端口访问
docker exec client curl http://192.168.1.100:8080
适用场景: 跨宿主机通信时,这是最基本的方式。
方式六:host 模式
docker run -d --network host --name web nginx
docker run -d --name client alpine
# 直接通过 localhost 访问
docker exec client curl http://localhost:80
注意: host 模式降低了网络隔离性,建议只在调试或性能敏感场景使用。
不同网络之间的容器
# 默认情况下,不同自定义网络之间的容器不能通信
docker network create net-a
docker network create net-b
docker run -d --name container-a --network net-a alpine sleep 3600
docker run -d --name container-b --network net-b alpine sleep 3600
# ❌ container-a 无法访问 container-b
docker exec container-a ping container-b # 超时
# 解决方法:将一个容器加入两个网络
docker network connect net-b container-a
# 现在 container-a 可以同时访问 net-a 和 net-b 中的容器
性能对比
| 方式 | 延迟 | 吞吐量 | 隔离性 |
|---|---|---|---|
| 自定义 bridge | 略有延迟 | 接近原生 | 好 |
| 共享网络命名空间 | 无额外延迟 | 原生 | 共享网络 |
| host 模式 | 无额外延迟 | 原生 | 无隔离 |
| 端口映射 | NAT 延迟 | 有损耗 | 好 |
最佳实践总结
# ✅ 推荐(生产环境)
# 同一微服务栈:用自定义 bridge + 容器名通信
docker network create --driver bridge microservice-net
# sidecar/代理模式:用共享网络命名空间
docker run --network container:main-container sidecar
# 跨宿主机通信:用端口映射 + 服务发现
# 或者更高级的 overlay 网络
总结
核心原则:用自定义 bridge + 容器名通信是生产首选。记住 — 容器通信的核心不是”能通”,而是”可发现、可管理、可隔离”。自定义 bridge 在这三方面做到了最佳平衡。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容