A cup of coffee
A heart set free

Docker容器网络互通配置指南:从连接拒绝到定位真凶

凌晨三点,我对着屏幕上那行 Connection refused 发呆。两个Docker容器,明明都在同一台机器上,却像失联了一样无法通信。我打开第六罐红牛,心想这事儿不应该这么复杂。事实证明,它确实不复杂,只是藏了很多坑等着你往里跳。🌃

问题的起点:两个世界的容器

看起来很简单的需求

我要做的事情听起来直白:让 LangBot 和 WeChatPadPro 两个服务互相通信。一个负责AI对话,一个对接微信消息,逻辑上它们应该是天然的搭档。

但现实给了我一巴掌。这两个服务分别跑在不同的 docker-compose 项目里,它们之间的距离,比我想象的要远。

第一次尝试的错误是这样的:

HTTPConnectionPool(host='127.0.0.1', port=1238): Max retries exceeded
Connection refused

我检查了端口占用,看了防火墙规则,确认服务在运行。一切看起来都正常,但就是连不上。就像你明明看见对方在线,消息就是发不出去,对方也收不到。

Docker重新定义了"本地"

在没有容器的时代,127.0.0.1 就是本机,同一台机器上的服务通过端口就能互相访问。Docker改变了这个规则

每个容器都是一个独立的运行环境。当你在容器内部访问 127.0.0.1 时,你访问的是容器自己,不是宿主机,更不是其他容器。这就像你站在自己房间里喊"有人吗",隔壁邻居是听不见的。

更麻烦的是,不同的 docker-compose 项目会创建各自的网络:

# WeChatPadPro 项目创建的网络
deploy_wechatpadpro-network

# LangBot 项目创建的网络  
docker_langbot-network

这两个网络就像两条平行线,永远不会相交。除非你做点什么。🔌

配置过程:一场细节的战争

第一步:创建一座桥梁

解决方案的核心思路是:创建一个外部网络,让两个项目的容器都加入进来

docker network create langbot-network

这个命令创建了一个独立于任何项目的网络。它不属于 WeChatPadPro,也不属于 LangBot,它是中立的公共区域。

如果执行时提示网络已存在,说明之前创建过,直接用就行:

Error response from daemon: network with name langbot-network already exists

这不是错误,反而是好消息——网络已经在那里了。

第二步:修改 WeChatPadPro 配置

打开 docker-compose.yml,找到网络配置部分。这里是最容易出错的地方

错误的写法:

networks:
  langbot-network:
    driver: bridge  # ❌ 这会创建新网络,不是使用外部网络

正确的写法:

networks:
  wechatpadpro-network:
    driver: bridge
  langbot-network:
    external: true  # ✅ 标记为外部网络

然后在服务配置里指定网络:

services:
  wechatpadpro:
    networks:
      - wechatpadpro-network  # 内部网络,访问数据库
      - langbot-network       # 外部网络,对外通信

  mysql:
    networks:
      - wechatpadpro-network  # 只在内部网络

  redis:
    networks:
      - wechatpadpro-network  # 只在内部网络

注意这个设计:MySQL 和 Redis 只在内部网络,外部容器无法直接访问它们。这是有意为之的安全设计。

第三步:修改 LangBot 配置

同样的道理,修改 LangBot 的配置:

services:
  langbot_plugin_runtime:
    networks:
      - langbot-network

  langbot:
    networks:
      - langbot-network

networks:
  langbot-network:
    external: true  # 不能少这行

关键点:网络名必须完全一致。langbot-networklangbot_network 是两个不同的网络,连字符和下划线的差异会让你的配置彻底失效。

第四步:重建容器

配置改完要生效,必须重建容器:

# WeChatPadPro 目录
docker-compose down
docker-compose up -d

# LangBot 目录
docker-compose down  
docker-compose up -d

启动时注意观察日志。正确的日志应该是:

Network langbot-network  External  ✓

如果看到这样的日志:

Network deploy_langbot-network  Created  ✗

说明配置还是错的,Docker 又创建了一个新网络,而不是使用外部网络。

第五步:验证网络

检查网络中的容器:

docker network inspect langbot-network

应该看到输出里包含三个容器:

  • wechatpadpro
  • langbot
  • langbot_plugin_runtime

然后测试连通性:

docker exec -it wechatpadpro ping langbot

能 ping 通就说明网络配置成功了。如果报错 ping: executable file not found,不用担心,这只是镜像里没装 ping 工具,不代表网络不通。换个方式:

docker exec -it langbot curl http://wechatpadpro:8080

那些让人抓狂的细节

127.0.0.1 的惯性思维

LangBot 的配置文件里最初写的是:

wechatpad_url: http://127.0.0.1:1238

在容器里,这个地址指向的是容器自己,不是 wechatpadpro。必须改成容器名

wechatpad_url: http://wechatpadpro:1238

Docker 的内置 DNS 会自动解析容器名到对应的 IP。这是容器间通信的标准做法。

external: true 的必要性

如果配置文件里只写:

networks:
  langbot-network:
    driver: bridge

Docker 会认为这是一个项目内的网络,会创建一个带项目前缀的新网络,比如 deploy_langbot-network

只有明确标记 external: true,Docker 才会去寻找已存在的外部网络:

networks:
  langbot-network:
    external: true

这一行,不能省。

网络名称的字符陷阱

Docker 网络名区分大小写,也区分连字符和下划线:

网络名 是否相同
langbot-network 基准
Langbot-Network ❌ 不同(大小写)
langbot_network ❌ 不同(下划线)
langbot-network ✅ 相同

我就在这个细节上卡了半小时。两个配置文件,一个用连字符,一个用下划线,看起来差不多,但 Docker 认为它们是两个完全不同的网络。

容器重启的必要性

修改 docker-compose.yml 后,必须重建容器才能生效。简单的 docker-compose restart 是不够的,因为网络配置在容器创建时就确定了。

必须用:

docker-compose down  # 删除容器
docker-compose up -d  # 重新创建

从网络问题到应用问题

错误信息的进化

配置完网络后,我以为一切搞定了。但 LangBot 还是报错:

500 Server Error: Internal Server Error for url: 
http://wechatpadpro:1238/login/GetLoginStatus

但这次的错误性质变了

  • 之前是 Connection refused —— 网络不通
  • 现在是 500 Server Error —— 网络通了,但接口报错

这说明网络层面已经没问题了,问题转移到了应用层。

WeChatPadPro 的真正问题

查看 wechatpadpro 的日志:

docker logs wechatpadpro --tail=50

发现了真相:

GET Connection locfree Failed by e36bdea0-f39a-4252-8fdc-913cf026e535
❌ 登录过程中发生panic
❌ 用户登录失败
登录初始化完成: 0/1 用户成功登录

原来问题不在网络,而在微信登录失败。WeChatPadPro 服务本身启动了,但微信账号没有成功登录,所以接口返回 500 错误。

分层排查的重要性

这个过程给我的启示是:问题要分层看

层级 问题表现 排查方法
网络层 Connection refused 检查网络配置、容器连通性
应用层 500/404 等HTTP错误 查看应用日志、检查服务状态
业务层 逻辑错误、数据异常 检查配置、验证业务流程

我的问题经历了这样的演进:

  1. 网络层:Connection refused → 配置外部网络解决
  2. 应用层:500 Server Error → 需要先完成微信登录

网络通了不代表服务能用,这是两个层面的问题。

未解决的部分

当前的状态

截至现在:

  • ✅ Docker 网络配置正确
  • ✅ 容器间可以互相访问
  • ✅ LangBot 能够请求 WeChatPadPro 的接口
  • ❌ WeChatPadPro 的微信登录失败
  • ❌ 整个服务链路还没跑通

问题从"网络不通"变成了"服务未就绪"。这是进步,但还没到终点。

下一步要做的事

根据 WeChatPadPro 的文档,需要:

  1. 访问 Swagger UIhttp://localhost:8080
  2. 填入 adminKey:从日志中获取
  3. 获取 token:调用 /admin/GanAuthKey 接口
  4. 扫码登录微信:调用 /login/GetLoginQrCodeNew 接口
  5. 在 LangBot 中配置:填入正确的 token 和 wxid

这些步骤都是业务层面的操作,和 Docker 网络无关了。但如果网络不通,连这些步骤都无法开始。

真实的技术工作

技术工作就是这样。你解决了一个问题,往往会发现另一个问题。问题不会消失,只会转移

网络配置花了我两个小时,定位到微信登录问题又花了一个小时。但至少现在我知道:

  • 网络没问题
  • Docker 配置没问题
  • 问题在 WeChatPadPro 的业务层

这就够了。定位问题比解决问题更重要,因为只有知道问题在哪儿,才能知道该往哪儿使劲。💪

配置检查清单

如果你遇到类似的 Docker 网络问题,按这个清单检查:

网络配置

  • [ ] 创建了外部网络 docker network create xxx
  • [ ] 两个 docker-compose.yml 的网络名完全一致
  • [ ] 网络配置都标记了 external: true
  • [ ] 服务配置中引用了正确的网络名

容器状态

  • [ ] 执行了 docker-compose downup -d
  • [ ] 启动日志显示 External 而不是 Created
  • [ ] 用 docker ps 确认所有容器都在运行
  • [ ] 用 docker network inspect 确认容器在同一网络

应用配置

  • [ ] 配置文件里用容器名替换了 127.0.0.1
  • [ ] 端口号正确(容器内部端口,不是映射的宿主机端口)
  • [ ] 相关的 token、密钥等配置正确

验证方法

  • [ ] docker exec 能在容器间通信
  • [ ] 接口返回的是业务错误而非连接错误
  • [ ] 查看了双方容器的日志

当网络层通了但服务还不工作时,停止折腾网络配置,去看应用日志。别在已经解决的问题上继续浪费时间。


天快亮了,外面传来早班公交车的声音。问题还没完全解决,但至少知道了问题在哪儿。有时候技术工作就是这样,你花大半夜时间,可能只是排除了一个方向,定位到了真正的问题。

但这就是进步。从漫无目的的摸索,到明确知道下一步要做什么,这就是价值。🌅

网络通了,剩下的就是业务问题了。那是另一个故事,也是明天的工作。现在,我需要睡觉。

赞(0) 打赏
未经允许不得转载:大神网 - 币圈投资与科技生活博客 » Docker容器网络互通配置指南:从连接拒绝到定位真凶

评论 抢沙发

登录

找回密码

注册