谁会遇到问题:用 Docker Compose 把 Gateway 与 openclaw CLI 分到不同容器,日志里 Gateway 似乎在跑,CLI 却卡在 gateway closed(WebSocket 1006/1008)、pairing required,或环境与文件里的两处 Token互相打架。本文结论:这不是「重装镜像就能好」的一类问题,而要把网关 URL(服务名或 Unix Socket)、OPENCLAW_GATEWAY_TOKEN 与配置里的 gateway.auth收敛到单一真源,并在必要时用共享网络命名空间收敛调用面。分工:与《子代理配对与 trustedProxies》并列——那边偏大类网段与白名单策略,本篇偏容器内如何「看见」网关与同源 Token;《Docker 网络分诊》《配对与 Token》《卷与权限》可交叉跳转。
127.0.0.1:127.0.0.1在每个容器里是自己的回环口,不会去另一个服务;必须用 Compose DNS 名(示例 http://openclaw-gateway:18789)。OPENCLAW_GATEWAY_TOKEN 可能覆盖配置文件;两侧容器若各读不同挂载副本,会表现为间歇 401/1008 交替出现。gateway.sock 暴露 Unix 域套接字,CLI 容器必须在完全一致的路径挂载该 socket 或其父目录,且权限与 UID/GID 对齐(见卷权限篇)。network_mode: service:<gateway>(占位服务名),或接受「全部走服务名 TCP」的一致性架构——两者勿混在同一套 env里。把上述五条当作白板检查项;任何一格仍待定,就不必先辩论「要不要换镜像 tag」——网络合同未闭合时换镜像通常无效。
实战中建议再补一栏时间线对齐:同一 WebSocket 关闭码出现后,截取毫秒级对齐的 Gateway stderr、CLI stdout、Docker events 三件事——半数「偶发」会被证明是另一侧服务重启或健康检查误杀。
| 症状快照 | 优先核查(自上而下) | 常见落点 |
|---|---|---|
1006 + 网关进程刚重启/OOM |
同一时间窗宿主 dmesg/Docker 重启策略 → 再找上游超时与健康检查 |
链路非正常关闭≠配对策略错 |
1008 + pairing required |
对齐 Token 同源 → CLI 网关 URL → 配对状态是否真的写在共享卷 | 双 Token 或未共享状态目录 |
Connection refused 仅在 CLI 容器内 |
把探测命令搬进 CLI 容器再跑;宿主 curl 仅能当旁证 | 127.0.0.1 误区或端口未 publish 到 CLI 视图 |
| 改用 Unix Socket 后 ENOENT/Permission denied | ls -la挂载点 → 宿主与容器 UID 映射 → 是否套娃目录 |
socket 父子目录未同框挂载 |
不要凭关闭码做单点结论:1006/1008 在浏览器与 WebSocket 栈里多半是症状标签;必须与网关日志前缀、配对状态机、同一时间窗的反代 Retry并读,否则容易被错误「扩大监听面」或「反复 onboard」带进更大暴露。
grep/docker compose config校对展开结果,杜绝「两处各写一半」。.openclaw/运行时目录:Gateway 与 CLI 必须看到同一份磁盘事实;状态目录只读会直接让配对「看起来永远在第一步」,《卷与权限对照》逐项过。openclaw gateway status → openclaw doctor,失败时把时间戳对齐到宿主与容器两侧的进程日志。network_mode: service:<gateway> 或服务网格侧替代方案,并在防火墙白名单上与《trustedProxies 篇》的参数一致。若团队同时跑着外层 Nginx/Caddy,《反代与 WS》里 Upgrade/Timeout 任一与 Compose 侧的网关 URL口径打架,会先表现为间歇 1006——这类问题只靠改 Gateway bind 往往会把暴露面铺大还治标不治本。
# 占位示例:请替换为你的服务名与实际路径;合并前请先 docker compose config 校验展开
services:
openclaw-gateway:
environment:
- OPENCLAW_CONFIG_DIR=/data/.openclaw
# 若坚持用环境 TOKEN,请在所有消费方对齐同一 env_file
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
volumes:
- oc-data:/data/.openclaw
# 若启用 Unix Socket,可把 socket 写入该卷下可读路径并与 CLI 共享
networks: [oc-net]
openclaw-cli:
environment:
- OPENCLAW_CONFIG_DIR=/data/.openclaw
- OPENCLAW_GATEWAY_URL=http://openclaw-gateway:18789
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
volumes:
- oc-data:/data/.openclaw
networks: [oc-net]
depends_on:
- openclaw-gateway
networks:
oc-net:
driver: bridge
volumes:
oc-data:
笔记本上单容器试玩 Gateway 还可以;一旦进入常驻自动化 + 多端配对 + Secrets 轮换,漂移的 Docker 宿主、睡眠策略与零碎挂载会把 Token/配对状态撕开。把 Gateway 固定在可数清重启次数的独占节点上——例如六国可选、可按月/季组合的 Apple Silicon云端 Mac——更利于与同区 CI Runner、密钥管理节奏对齐:MACCOME提供更接近「小规模生产」的拓扑承载面;可先参阅公开租赁档位与帮助中心,再回填本文 Runbook 中的环境字段。
OpenClaw 在 Compose 场景的失败模式几乎总是网络命名空间/Token/状态目录三件事未写成一条合同。在未收敛单一真源前,不要盲目「换镜像」「关 TLS」——会把排错带进安全债。评审会上若出现「先改代码还是先改基础设施」的争吵,用一句话压制:哪一侧能展示可重复的容器内握手成功包,就以哪一侧的合同为准——其它讨论一律排队。
对齐后再与《GHCR Control UI Runbook》《反向代理与 TLS》做下一跳集成。
常见问题
本篇与 4 月《子代理配对 1008 + trustedProxies》有什么分工?
那边偏大网段、白名单与子代理链路;本篇把Gateway URL、TOKEN 同源、Unix Socket、共享命名空间下的最短闭环写清,两边应互联阅读而不是择一丢弃。
宿主机能 curl 通 18789,是否等于流水线一定通?
不等于。必须在报错同一容器镜像里执行等价探测;命名空间不一致时宿主结果只是噪音。