背景

OpenClaw 是一个开源的自托管 AI 助手框架,可以连接 Telegram、WhatsApp、Discord 等多个消息平台,通过 AI 模型处理消息并执行任务。相比于 Claude Code(专注于代码开发),OpenClaw 更像是一个"生活管家",可以通过消息平台远程控制服务器、自动化日常任务。

今天在腾讯云轻量应用服务器(4核4G,Ubuntu 20.04)上完成了 OpenClaw 的部署,整个过程遇到了一些典型的网络和配置问题,记录下来供参考。

核心挑战

1. Docker 镜像拉取问题

腾讯云服务器访问 Docker Hub 和 GitHub 非常不稳定:

  • docker pull 经常超时
  • GitHub HTTPS 连接失败(GnuTLS recv error -54)
  • npm registry 可以访问,但 GitHub 不行

解决方案:部署 Clash 代理 + 配置 Docker 使用代理

2. 容器网络配置

OpenClaw 默认配置 bind: "loopback" 在容器内无法正常工作,导致 Gateway 启动后端口不监听。

解决方案:修改配置为 bind: "lan"

3. 卷挂载路径问题

docker-compose 中使用 ~/.openclaw 在 sudo 执行时会指向 root 用户的 home 目录,导致配置文件无法正确挂载。

解决方案:使用绝对路径 /home/ubuntu/.openclaw

部署流程

第一步:部署 Clash 代理

由于网络问题,首先需要解决服务器的出站访问。选择 Mihomo (Clash Meta) 作为代理客户端:

# 下载并安装
wget https://github.com/MetaCubeX/mihomo/releases/download/v1.18.10/mihomo-linux-amd64-v1.18.10.gz
gunzip mihomo-linux-amd64-v1.18.10.gz
sudo mv mihomo /usr/local/bin/clash
sudo chmod +x /usr/local/bin/clash

使用订阅方式配置 Clash(推荐):

# 下载订阅配置
curl -o /etc/clash/config.yaml http://your-subscription-url/clash-config.yaml

# 或手动创建配置文件,配置代理节点
# 注意:不要在公开文档中暴露真实的代理配置

配置 systemd 服务并启动:

sudo systemctl start clash
sudo systemctl enable clash

验证代理:

curl -I --proxy http://127.0.0.1:7897 https://www.google.com
# HTTP/1.1 200 Connection established

第二步:配置 Docker 代理

为 Docker daemon 配置代理,使其能够拉取镜像:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null << 'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7897"
Environment="HTTPS_PROXY=http://127.0.0.1:7897"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

同时配置国内镜像源作为备用:

sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://docker.1panel.live",
    "https://hub.rat.dev"
  ]
}
EOF

验证配置:

sudo systemctl show --property=Environment docker
# Environment=HTTP_PROXY=http://127.0.0.1:7897 HTTPS_PROXY=http://127.0.0.1:7897 ...

sudo docker pull node:22-slim
# 成功拉取

第三步:部署 OpenClaw

根据官方文档,OpenClaw 推荐使用预构建镜像:

sudo mkdir -p /opt/openclaw
cd /opt/openclaw

# 拉取镜像
sudo docker pull ghcr.io/openclaw/openclaw:latest

创建 docker-compose.yml

version: '3.3'

services:
  openclaw:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw
    restart: unless-stopped
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
      - ANTHROPIC_BASE_URL=${ANTHROPIC_BASE_URL}
    volumes:
      - /home/ubuntu/.openclaw:/home/node/.openclaw
    ports:
      - "127.0.0.1:18789:18789"

创建 .env 文件(包含 API 密钥)。

第四步:初始化配置

运行 onboarding 向导生成配置文件:

sudo docker run --rm \
  -v /home/ubuntu/.openclaw:/home/node/.openclaw \
  -e ANTHROPIC_API_KEY=your_key \
  -e ANTHROPIC_BASE_URL=your_url \
  ghcr.io/openclaw/openclaw:latest \
  node openclaw.mjs onboard \
  --non-interactive \
  --accept-risk \
  --auth-choice anthropic-api-key \
  --anthropic-api-key your_key \
  --gateway-bind loopback \
  --gateway-port 18789

关键修复:修改生成的配置文件,将 bindloopback 改为 lan

sed -i 's/"bind": "loopback"/"bind": "lan"/g' /home/ubuntu/.openclaw/openclaw.json

这是因为在 Docker 容器内,loopback 模式无法让宿主机访问容器端口。

第五步:启动并验证

sudo docker-compose up -d

# 等待几秒后验证
curl http://127.0.0.1:18789/healthz
# {"ok":true,"status":"live"}

成功!Gateway 已经运行。

踩过的坑

1. 日志为空的困惑

容器启动后,docker logs openclaw 一直为空,但进程确实在运行。这是因为 OpenClaw 默认不输出到 stdout,日志写入到 /home/node/.openclaw/logs/ 目录。

2. 端口不监听

最初使用 bind: "loopback" 配置,容器启动后端口始终不监听。通过 cat /proc/net/tcp 确认端口确实没有打开。改为 bind: "lan" 后立即解决。

3. 配置文件挂载失败

使用 ~/.openclaw 作为卷挂载路径时,sudo 执行 docker-compose 会将 ~ 解析为 /root,导致配置文件无法正确挂载。必须使用绝对路径。

4. 代理模式选择

最初尝试将 Clash 设置为 mode: global,但这会导致所有流量都走代理,包括访问本地服务。改回 mode: rule 后,通过规则控制哪些流量走代理更合理。

架构总结

最终的部署架构:

Internet
   ↓
VPS 代理节点
   ↓
Clash (127.0.0.1:7897) - 本地代理
   ↓
Docker Daemon - 通过代理拉取镜像
   ↓
OpenClaw Container (127.0.0.1:18789) - Gateway 服务

下一步

  1. 配置 Telegram Bot:创建 Bot 并连接到 OpenClaw
  2. 反向代理:通过 Nginx 或 Caddy 暴露 Gateway(可选)
  3. 监控告警:配置健康检查和自动重启
  4. 数据备份:定期备份 /home/ubuntu/.openclaw 目录

经验总结

  1. 网络问题优先解决:在国内服务器上部署国外服务,代理是必需品
  2. 容器网络配置要注意:容器内的网络环境与宿主机不同,loopbacklan 的行为差异很大
  3. 路径使用绝对路径:避免 ~ 符号在不同用户环境下的歧义
  4. 日志位置要清楚:不是所有应用都输出到 stdout,要知道日志文件在哪
  5. 官方文档是基础:遇到问题先查官方文档,社区方案可能已经过时

参考资源


完整的部署文档和配置文件已整理到项目 docs 目录,后续可以直接参考复用。