15.6.3 容器间通信与服务发现

容器间通信与服务发现#

1. 通信原理#

  • 同一用户自定义桥接网络:容器通过 veth 接入 Linux bridge,使用容器 IP 直连
  • 不同网络:需显式加入多个网络或通过网关/路由转发
  • DNS:Docker 内置 DNS 127.0.0.11 解析容器名与别名
文章图片

2. 环境准备与网络创建(示例)#

# 1) 创建自定义网络(带子网)
docker network create --driver bridge --subnet 172.18.0.0/16 ops-net

# 2) 启动两个容器加入同一网络
docker run -d --name web --network ops-net -p 8080:80 nginx:1.25
docker run -d --name api --network ops-net alpine:3.19 sleep 3600

# 3) 在 api 容器内安装工具(安装示例)
docker exec -it api sh -c "apk add --no-cache curl bind-tools"

3. 基于容器 IP 的直连(示例与说明)#

  • 适用于测试;重建容器 IP 可能变化
  • 查看 IP 并访问
# 获取容器 IP
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web

# 在 api 容器内访问 web(替换为上一步 IP)
docker exec -it api curl -s http://172.18.0.3:80 | head -n 2

命令解释
- docker inspect -f:格式化输出容器网络信息
- curl -s:静默请求并输出内容

4. 基于容器名的服务发现(推荐)#

  • 同一自定义网络内,容器名即 DNS 记录
  • Compose 中使用服务名更稳定
# 容器名解析与访问
docker exec -it api nslookup web
docker exec -it api curl -s http://web:80 | head -n 2

预期效果
- nslookup web 返回 172.18.x.x
- curl 返回 Nginx 欢迎页片段

5. 链接与别名(别名切换示例)#

# 给 web 增加别名 v1(网络别名)
docker network connect --alias v1 ops-net web

# 用别名访问
docker exec -it api curl -s http://v1:80 | head -n 2

说明
- --alias 用于同一网络内多名称解析,便于灰度或多版本共存

6. 跨网络通信(加入多网络)#

# 创建另一个网络
docker network create --driver bridge 172net

# 将 api 加入 172net(多网卡)
docker network connect 172net api

# 查看容器多网卡 IP
docker inspect -f '{{json .NetworkSettings.Networks}}' api | jq .

风险提示
- 多网络路由冲突会导致访问异常,需检查默认路由与子网是否重叠

7. 服务发现常见模式(含反向代理示例)#

  • DNS 轮询:多个副本共享同一服务名
  • 反向代理:统一入口转发到后端
  • 注册中心:Consul/Etcd/Nacos 提供动态注册

Nginx 反向代理示例(容器内配置)

# /etc/nginx/conf.d/upstream.conf
upstream api_upstream {
    server api:8080;
    server api2:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://api_upstream;
    }
}

8. 通信排错流程(命令与解释)#

# 1) 网络是否存在
docker network ls

# 2) 容器是否在网络内
docker network inspect ops-net | jq '.[0].Containers'

# 3) 容器内 DNS 是否正常
docker exec -it api cat /etc/resolv.conf
docker exec -it api nslookup web

# 4) 端口是否监听
docker exec -it web ss -lntp | grep ':80'

# 5) 宿主机 NAT 规则(端口映射异常时)
iptables -t nat -L -n | grep 8080

常见故障定位
- DNS 失败:容器不在同一自定义网络
- 连接超时:目标服务未监听或容器进程异常
- 端口映射失败:宿主机端口被占用

9. 练习(含目标与验证)#

1) 练习1:容器名访问
- 目标:api 访问 web
- 验证:docker exec -it api curl -s http://web:80 | head -n 1

2) 练习2:多别名灰度
- 目标:给 web 增加别名 gray
- 验证:docker exec -it api nslookup gray

3) 练习3:跨网络加入
- 目标:为 api 加入第二个网络并查看双 IP
- 验证:docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}} {{end}}' api

10. 生产实践建议#

  • 统一使用自定义网络,避免依赖默认 bridge
  • 生产访问使用服务名 + 反向代理或注册中心
  • 多副本服务配合健康检查与负载均衡
  • 记录网络规划与子网划分,避免重叠冲突