2026 OpenClaw Docker 网络分诊清单
CLI 连不上 Gateway——Compose 网络、bind 与命名空间对照修复

约 22 分钟阅读 · MACCOME

已用 Docker Compose 跑 OpenClaw的开发者里,最高频的挫败往往不是「镜像拉不下来」,而是Gateway 日志看似正常、浏览器或 CLI 却反复报连接被拒绝 / WebSocket 失败 / token 无效——其中大量案例根因在监听地址(bind)、端口发布、以及 CLI 与 Gateway 是否共享同一网络命名空间,而不是模型密钥本身。📌 本文给出六类可写进值班的网络症状、两张「进程已起 vs 路由可达」对照表、bind/防火墙/发布端口矩阵、可复制诊断命令、六步 Runbook 与三条应写进日志检索的硬口径;并与站内《Docker 与 Gateway 生产向 Runbook》《doctor 与装后排错》《K8s 探活与滚动更新》分工——生产篇管「怎么部署」,本篇管「包在跑但包与包、包与宿主机之间为什么互相看不见」

先把症状分类:六类「像 token 问题、其实是网络」的假象

OpenClaw 的控制面通常由 Gateway WebSocket/HTTPCLI / Control UI 组成;Docker 场景下还会叠加 多个容器、自定义 bridge、以及 network_mode: service:... 等组合。若不做分层分诊,团队会在 .openclaw 与环境变量之间来回改,却不去看监听地址是否真的落在 CLI 可达的接口上。

  1. 仅 loopback 监听:Gateway 在容器内只绑 127.0.0.1,宿主机通过 published port 访问时由代理层转发看似可通,但同 compose 内另一容器用服务名访问时却落到错误的协议视图。
  2. CLI 与 Gateway 分属两个 network namespace:CLI 容器解析 gateway:18789 走了 bridge DNS,而 Gateway 实际只向 service 侧暴露回环套接字——表现为间歇性「第一次能连、重启用后全挂」。
  3. published port 映射到错误 target:Compose 将宿主机 18789 指到旧容器 IP,滚动升级后 iptables 规则残留,宿主机 curl 偶发成功、容器内始终失败。
  4. 宿主机防火墙 / 云安全组放行公网却阻断 bridge:本机 loopback 与 docker0 转发策略不一致,导致「本机浏览器 OK、同机另一个 namespace 的 CLI 不 OK」。
  5. 反代或 Tunnel 只处理了 HTTP,没升级 WebSocket:日志里出现握手失败,常被误判为 Gateway 崩了;实为路径或 Upgrade 头在边缘被剥掉(与《Linux systemd + Tunnel》路径互补)。
  6. 双栈或强制 IPv6:容器内优先走 ::1 或错误 AAAA,宿主机仅 IPv4 通——在部分云 Mac 或精简镜像上会被放大。

把上述条目与《生产 Runbook》里的卷、镜像标签、健康检查放在同一变更单上:前者回答控制面是否可达,后者回答进程是否按预期版本在跑

实务上建议在 compose 仓库里维护一页「网络拓扑说明」:画出 Gateway、CLI、可选的 edge 反代各自落在哪个 network、哪些端口由谁 publish、以及开发机与 CI 分别从哪里探测。没有这张图时,排障对话会反复落在「你是不是改了我本机的 hosts」这类不可审计路径上。再补充一点:Docker 的 DNS 解析在自定义网络与默认 bridge 上行为并不相同,服务名解析失败时不要先怀疑 OpenClaw 本身,先用 docker compose exec 进容器跑 getent hostsnslookup 确认名字是否落在预期 IP。

表 1:Gateway「未起」与「起了但不可路由」— 先判读哪一类

第一步永远用官方 CLI 做存活与版本对齐(见《doctor 篇》),再进入下表。不要在未确认进程监听之前就改 token。

观测更可能类别优先动作常见误操作
docker ps 无 Gateway 容器或持续重启未起 / CrashLoopdocker logs、资源限制、镜像 digest、健康检查是否误杀反复 docker compose pull 却不看 OOM
容器 Running,但 ss -lntp(容器内)无监听配置未加载 / 绑定失败核对环境变量 OPENCLAW_GATEWAY_BIND 与 compose command;对照官方 Docker 文档中的 bind 枚举只改宿主机 /etc/hosts
容器内监听正常,CLI 容器 wget 失败跨 namespace 路由检查是否应使用 network_mode: "service:gateway" 或统一自定义网络别名把 Gateway 改成 0.0.0.0 却不理解暴露面
仅宿主机浏览器失败、容器内成功端口发布 / 本机代理核对 ports: 映射、本机 VPN/代理、以及是否误用 localhost 解析到代理 PAC盲目关闭 Gateway TLS 选项

表 2:gateway.bind、端口发布与防火墙—对照矩阵(Docker 专用读法)

下列读法与官方文档中「bind 取 loopback / lan / tailnet / auto 等枚举」一致;Compose 里还要把谁负责 publish写清。

目标典型 bind / 环境变量思路Compose 注意点安全边界
仅本机开发机自测偏向 loopback;由宿主机浏览器访问 published port127.0.0.1:18789:18789 限制暴露面不要把 loopback 误当成「同 compose 其他服务默认可达」
同 compose 内 CLI 与 Gateway 强一致让 CLI 共享 Gateway 的网络栈network_mode: "service:openclaw-gateway"(服务名以你的文件为准)共享栈意味着共享端口空间;避免重复监听冲突
局域网其他设备调试lan 或等效;确保监听非仅 127.0.0.1明确 ports 绑定 0.0.0.0 还是宿主机具体 IP配合上游防火墙最小放行
经 Tunnel / 反代对外Gateway 仅回环,边缘终止 TLS分离 gatewayedge 网络;校验 WebSocket 透传禁止把管理口直接对公网裸暴露
bash
# 1) 宿主机:端口是否真的发布成功
docker compose ps
curl -sv --max-time 2 http://127.0.0.1:18789/  || true

# 2) 进入 gateway 容器查看监听(镜像若有 ss/busybox 则用之)
docker compose exec openclaw-gateway sh -lc 'ss -lntp 2>/dev/null || netstat -lntp'

# 3) 从「CLI 容器」视角探测(服务名替换为你的 compose service)
docker compose exec openclaw-cli sh -lc 'wget -qO- --timeout=2 http://openclaw-gateway:18789/ || echo FAIL'

# 4) 对照网络命名空间(是否应 network_mode: service:...)
docker compose config | sed -n '1,200p'
warning

注意:社区 issue 中常见「CLI 无法连接 Gateway」与 compose 未让 CLI 与 Gateway 共享网络命名空间相关:修改前先在测试 compose 上验证第三节命令块,再合并到生产文件。

六步 Runbook:从「能复现」到「能写进变更记录」

下列步骤假设你已能拉取镜像;若尚未完成安装入口,请先读《三平台安装与平台选择》。

  1. 冻结 compose 片段:把 Gateway、CLI(若有独立服务)、卷挂载与环境变量导出为单一 Git 版本,避免「手改运行态」与仓库不一致。
  2. 跑 doctor 与 gateway status:确认版本与配置路径一致,排除 token 文件多份(与《装后排错》对齐)。
  3. 按表 1 区分未起 vs 不可路由:对 Running 容器执行监听检查与跨容器 wget/curl
  4. 按表 2 调整 bind 与 network_mode:一次只改一个变量;每步重跑第三节命令块留证据。
  5. 若经 Tunnel/反代:在边缘抓 Upgrade 与路径重写,再回到 Gateway 日志对照(与 Tunnel 篇分工)。
  6. 写入值班主任摘要:记录「监听地址、compose service 名、是否共享 network namespace、以及一条成功的探测命令输出摘要」。

三条应写进日志检索与告警的「硬核」口径

下列字段把「偶发连不上」变成可对比回归的信号,并与《K8s 探活篇》中的 HTTP 探针字段兼容(迁移到编排时可直接映射)。

  1. 监听三元组:容器内 ss 输出的 Local Address:Port + 进程名 + compose 服务名;任一变更必须出现在变更单。
  2. 跨命名空间探测结果:CLI 容器到 Gateway 的 HTTP/TCP 结果(成功/超时/DNS 失败)分桶统计;DNS 失败与连接超时是不同根因。
  3. 端口发布一致性:宿主机 docker port 与实际 iptables NAT 规则是否在滚动后仍指向当前任务 IP;2026 年常见「升级后旧链残留」导致的幽灵故障。

补充:将 Gateway 日志中握手失败上游模型 429/5xx分标签统计;若后者占比高,应回到《provider 降级篇》,而不是继续调 compose 网络。

若你已启用《K8s 探活篇》里的 HTTP 健康检查,请把探针目标 URL与本文表 2 的 bind 策略对齐:探针若只打 loopback 而实际流量从另一网卡进入,会出现「探活全绿、用户全红」的错位;这类问题在滚动发布窗口最容易被误报为「新版本坏了」。

为什么「只在笔记本本机跑 Docker」难撑长期控制面

个人笔记本上的 Docker Desktop 睡眠、VPN 切换与本地代理常改变 localhost 解析与端口转发行为;一旦要把 Gateway 交给团队共用或交给 Agent 长期值守,就需要可重复的监听策略、可审计的 compose 版本与稳定的宿主机网络边界。纯本地堆叠也难以同时提供多地区低延迟出口与物理机级隔离,与生产级自动化对「控制面总在可达位置」的要求相冲突。

对需要把 Gateway 放在可值班、可横向扩展且网络边界清晰的环境的团队而言,将控制面落在专业云 Mac / 多地区节点上,通常比依赖不稳定个人设备更符合节奏。MACCOME 在新加坡、日韩、香港与美东美西等提供 Mac Mini M4 / M4 Pro 物理节点与弹性租期,适合作为 OpenClaw 与 Apple 工具链共存的常驻执行平面;网络分诊完成后,可在《SSH 与 VNC 指南》与帮助中心核对接入方式,再按公开价格与区域页落单。

试点建议:先在独占测试机上把表 1、表 2 与命令块跑通并归档日志,再推广到共享 compose 仓库,避免「口口相传的 network_mode」无法复盘。

最后强调:任何把 Gateway 绑定到 0.0.0.0 以「先跑起来再说」的临时方案,都应在变更单里写明回滚时间与暴露面评估;网络分诊的目标不是无限扩大监听范围,而是让「谁该看见控制面」与 compose 文件中的命名空间设计一致,这样值班同学才能在五分钟内向研发说明白根因。

常见问题

这篇和「Docker 生产与 Gateway 常驻」有什么不同?

生产篇写镜像、卷、健康检查与发布;本篇只写控制面可达性。装后验证入口见 帮助中心,并与《Docker 生产 Runbook》互链。

WSL2 上是否适用同一套表?

分诊顺序一致,但 localhost 转发与 systemd 行为不同;请叠加《doctor 与 WSL2 排错》中的症状对照。

还要对比地区与租期去哪看?

若计划把 Gateway 放在云端 Mac,先用《多地区节点指南》与 租赁价格 对齐主链路,再定 SSH 出口与防火墙策略。