容器间通信方式

容器间通信方式

面试题

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:
# 老版本 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
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容