说实话,我写这篇文章的时候,心情是复杂的。

你在网上搜 OpenClaw 部署教程,搜到的大概率是官方文档或者某篇"三步搞定 OpenClaw 部署"的博客。看起来特别简单对吧?docker compose 一拉,配置一填,服务就跑起来了——理论上是这样。

但现实是,我从拉下 docker-compose.yml 到真正跑通所有功能,整整折腾了一个周末。中间遇到的每一个坑,搜遍 Google 和 GitHub Issues 都找不到有人写过。


坑 1:Docker Volume 权限 EACCES——上来就给我一闷棍

症状

容器起不来,日志报 EACCES: permission denied, mkdir '/home/node/.openclaw/state'

原因

宿主机用 root 创建的数据目录(UID 0),但容器内 node 用户 UID 是 1000,权限不匹配。

修复

sudo chown -R 1000:1000 /opt/openclaw/data
教训:Docker volume 挂载,永远注意容器内运行用户的 UID。

坑 2:docker compose exec 超时——命令卡死不动

症状

docker compose exec openclaw-gateway node dist/index.js config set ... 卡死无响应。

原因

exec 连到正在运行的 gateway 进程的 stdin,而 gateway 主进程不为 CLI 指令服务。

修复

docker compose run --rm -T openclaw-cli node dist/index.js config set gateway.mode local
教训:exec 是连到已有进程,run 是启动新容器。CLI 操作一律用 run --rm -T。

坑 3:阿里云 ICP 备案拦截 HTTP 80 端口——大陆特色坑

症状

acme.sh HTTP-01 验证失败,curl 返回的 Server 头是 Beaver(阿里云备案检查网关)。

原因

阿里云大陆服务器对所有 HTTP 80 端口流量强制 ICP 备案检查,即使主域名已备案,子域名 HTTP 流量照样被拦截。

修复

放弃 HTTP-01 和 ALPN-01,只走 DNS-01 + 443 端口

教训:大陆阿里云 = 80 端口不可用于任何验证流程。

坑 4:acme.sh HTTP-01 和 ALPN-01 验证全部失败

症状

ALPN-01 走 443 端口 TLS 验证,但 acme.sh 预检查(pre-check)仍走 80 端口——又被拦截。

修复

DNS-01 手动验证:

acme.sh --issue -d claw.example.com --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please

添加 TXT 记录后

acme.sh --renew -d claw.example.com

教训:DNS-01 是最可靠的证书验证方式,不依赖服务器端口。

坑 5:ZeroSSL CA 卡住 retryafter=86400——等 24 小时?

症状

acme.sh 返回 retryafter=86400,要等一天。

原因

acme.sh 默认 CA 从 Let's Encrypt 切换到了 ZeroSSL,ZeroSSL 有时返回超长 retry-after。

修复

acme.sh --set-default-ca --server letsencrypt
教训:acme.sh 默认 CA 已经变了,卡住时先检查 acme.sh --info

坑 6:gateway.token 不是有效的 config key

症状

config set gateway.token my-secret-token 报 Unrecognized key: "token"

原因

Gateway Token 不通过配置文件设置,而是通过环境变量 OPENCLAW_GATEWAY_TOKEN 传入。

修复

在 docker-compose.yml 的 environment 中添加:

environment:
  - OPENCLAW_GATEWAY_TOKEN=my-secret-token
教训:敏感凭证走环境变量,业务配置走 config file。

坑 7:heartbeat.activeHours 格式错误

症状

config set agents.defaults.heartbeat.activeHours "08:00-23:00" 报 expected object, received string

原因

activeHours 字段期望 JSON 对象 {"start": "08:00", "end": "23:00"},不是字符串。

修复

docker compose run --rm -T openclaw-cli node dist/index.js config set agents.defaults.heartbeat.activeHours '{"start":"08:00","end":"23:00"}' --strict-json
教训:不确定格式时,加 --strict-json 传 JSON 对象。

坑 8:Gateway 启动报 "Missing config"——鸡生蛋蛋生鸡

症状

gateway 启动后立即退出:Missing config. Run openclaw setup or set gateway.mode=local

原因

OpenClaw gateway 启动前检查配置文件,未配置则拒绝运行。但第一次部署时确实还没有配置。

修复

用临时容器先做初始化配置,再启动:

docker compose run --rm -T openclaw-cli node dist/index.js config set gateway.mode local
docker compose up -d
教训:先配置,再启动。用 docker compose run 创建临时容器做初始化。

总结

# 问题 核心原因 一句话解决
1 Volume 权限 EACCES 宿主机 root vs 容器 node(UID 1000) chown -R 1000:1000
2 exec 超时卡死 gateway 进程不接收 CLI stdin 改用 run --rm -T
3 80 端口被备案拦截 阿里云大陆强制 ICP 检查 走 DNS-01 + 443
4 HTTP/ALPN 验证失败 80 端口不可用 DNS-01 手动 TXT
5 ZeroSSL 卡 24 小时 默认 CA 变了 切回 Let's Encrypt
6 token 不是 config key Token 走环境变量 设 OPENCLAW_GATEWAY_TOKEN
7 activeHours 格式错误 要 JSON 对象不要字符串 --strict-json + JSON 对象
8 Missing config 启动失败 未配置不允许启动 先 run 配基础再 up

部署一个新工具的过程,往往是文档里 5 分钟、实际操作 5 小时。希望这篇文章帮你省了至少 4 个小时。

更多推荐