【Docker】docker swarm中overlay网络的组建,排错案例,docker config的更新
容器间无法通过服务名互相访问(报),并且有作为拨号目标导致连接失败;此外浏览器重定向尝试访问也失败。Swarm 内服务 DNS 不生效 →。浏览器访问外部主机时使用了 Swarm 内部服务名 → 浏览器无法解析mediahub。
Docker Swarm 网络互通 — 一个从故障到解决的简明实战教程(初学者友好)
下面把你这次的排查与解决流程精简、结构化地整理成一篇小 blog。目标是让初学者能一步步看懂:为什么容器间不能用服务名通信、如何修复、以及浏览器访问与服务名的区别。文中穿插命令、表格和 > 注解,便于复制执行和复用。
一、问题概述(一句话)
容器间无法通过 服务名 互相访问(报 no such host),并且有 0.0.0.0:50052 作为拨号目标导致连接失败;此外浏览器重定向尝试访问 http://mediahub:5174/ 也失败。
实际症状归为两类:
- Swarm 内服务 DNS 不生效 →
lookup xxx on 127.0.0.11:53: no such host。- 浏览器访问外部主机时使用了 Swarm 内部服务名 → 浏览器无法解析
mediahub。
二、核心概念速览(非常重要,读懂就好)
-
Overlay 网络(Swarm):Swarm 的容器互通依赖 overlay 网络与内建 DNS。只有加入同一 overlay 网络的服务,才能互相通过
service-name解析到对方。 -
服务名解析范围:
service-name仅在 Swarm overlay 网络内部可解析,浏览器/宿主机不认识该域名。 -
监听地址 vs 拨号目标:
0.0.0.0用于监听(表示“所有网卡”),不能作为客户端拨号目标;- 客户端拨号应使用
service-name:port(跨容器)或127.0.0.1:port(同容器/同主机)。
-
Config 挂载(docker config):如果配置是通过
docker config挂载的,可以不重建镜像,按service update --config-rm→docker config rm→docker config create→service update --config-add的顺序更新。
小提示:Alpine 镜像没有
bash,用sh进入容器;在容器内用netstat/ss检查监听地址。
三、你做了什么(关键命令与结果)
- 创建 overlay 网络并加入服务:
docker network create --driver overlay app-net
# 把服务加到同一网络(示例)
docker service update --network-add app-net user
docker service update --network-add app-net user-crontab
docker service update --network-add app-net mediahub
docker service update --network-add app-net shorturl
docker service update --network-add app-net shorturl-proxy
- 验证服务是否加入网络:
docker service inspect user --format '{{json .Spec.TaskTemplate.Networks}}'
# 期望结果包含 app-net 的 network id
- 在容器内看监听地址(示例):
docker exec -it <container_id> sh
# 容器内执行
netstat -tlnp
# 例如看到:127.0.0.1:8080 -> 说明只能容器内部 loopback 访问
- 测试服务名解析(在容器内):
docker exec -it <user_container_id> ping -c2 user-crontab
四、为什么你一开始会遇到那些错误(归纳)
| 报错/现象 | 根本原因 | 说明 |
|---|---|---|
no such host(lookup user-crontab …) |
服务未加入同一个 overlay 网络 / 没有 Swarm DNS 路径 | Swarm DNS 只在 overlay 网络生效 |
dial tcp 0.0.0.0:50052: connect: connection refused |
客户端拨号使用 0.0.0.0(错误) |
0.0.0.0 只能监听,不能作为目标拨号地址 |
浏览器访问 http://mediahub:5174 失败 |
mediahub 是 Swarm 内部名,外部 DNS/主机无法解析 |
浏览器需访问宿主 IP 或域名(例如 http://192.168.132.134:8080) |
注:在本地开发(server 和 client 在同一台机器)
0.0.0.0/localhost有时“蒙对”导致看似正常,但分布式环境下会暴露问题。
五、操作步骤(按顺序复制执行) — 把你的集群弄通用这 7 步
下面写出的命令基于你现有的服务名(mediahub、user、user-crontab、shorturl、shorturl-crontab、shorturl-proxy)。你已经执行了部分操作(创建 app-net 并加入服务),这里列出完整核查与补充步骤。
- 创建 overlay 网络(如果还没创建):
docker network create --driver overlay app-net
- 把所有相关 service 加入同一个网络:
docker service update --network-add app-net user
docker service update --network-add app-net user-crontab
docker service update --network-add app-net mediahub
docker service update --network-add app-net shorturl
docker service update --network-add app-net shorturl-crontab
docker service update --network-add app-net shorturl-proxy
- 验证服务已在网络上(任意服务举例):
docker service inspect user --format '{{json .Spec.TaskTemplate.Networks}}'
- 在容器内测试 DNS 分辨(在 user 容器里 ping user-crontab):
# 找到 user 的运行容器 id(示例)
CID=$(docker ps --filter "name=user.1" -q)
docker exec -it $CID ping -c2 user-crontab
- 检查服务监听地址(防止只监听 localhost):
docker exec -it $CID sh
# 容器内
netstat -tlnp
# 或
ss -tln
期望:应用监听在 0.0.0.0:PORT 或 :PORT(这两者等效,均可被外部访问)。
- 修复 gRPC / 内部拨号代码(示例,Go):
// server 应该 listen ":50052"
lis, _ := net.Listen("tcp", ":50052")
// client 在 Swarm 内跨服务拨号
conn, err := grpc.Dial("user-crontab:50052", grpc.WithInsecure())
注:如果 client 与 server 在同容器中,拨
127.0.0.1:50052;如果跨容器则拨service-name:port。
- 浏览器回调/重定向配置(
internalSystemEntry)
- 开发(本地前端):
http://localhost:5174 - 集群/局域网部署:填写宿主机 IP 或域名,例如:
internalSystemEntry:
mediahub: "http://192.168.132.134:5174"
浏览器必须能解析该地址 ——
mediahub:5174只对容器内部有效,不可直接作为浏览器 URL。
六、配置管理:docker config 的快速更新命令
如果你是通过 docker config 挂载配置文件,更新流程如下(以 user 为例):
# 1. 解除服务对旧 config 的使用
docker service update --config-rm user-conf user
# 2. 删除旧 config(只在上一步成功后允许删除)
docker config rm user-conf
# 3. 创建新 config(本地 dev.config.yaml 的路径视情况而定)
docker config create user-conf user/dev.config.yaml
# 4. 把新 config 挂回服务
docker service update --config-add source=user-conf,target=/app/config.yaml user
注:
docker config rm会在 config 正被 service 使用时失败,因此必须先--config-rm。
七、常见问题与快速排查(Checklist)
- 服务名解析失败 → 检查两个服务是否在同一 overlay 网络:
docker service inspect <svc> --format '{{json .Spec.TaskTemplate.Networks}}'。 - 容器间能 DNS 解析但连接被拒绝 → 检查目标容器是否在 相应端口 上监听
0.0.0.0:netstat -tlnp。 - 使用
0.0.0.0作为拨号目标 → 改为service-name:port或127.0.0.1:port。 - 浏览器访问
http://service-name:port失败 → 这是正常,因为该 name 仅作用于 Swarm 网内 DNS;改为宿主机 IP/域名。 docker config rm报错 → 先docker service update --config-rm解绑定。
八、简短示例
-
内部服务调用(推荐)
user→user-crontab:grpc.Dial("user-crontab:50052")- 两个服务在
app-netoverlay 网络上。
-
浏览器重定向(外部访问)
- 回调重定向到:
http://192.168.132.134:8080/(或域名),不要用mediahub:5174。
- 回调重定向到:
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)