侧边栏壁纸
博主头像
大脸猫博主等级

不气~不气~人生就是一场大戏

  • 累计撰写 19 篇文章
  • 累计创建 2 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

CLAWPANEL + OPENCLAW 汉化版 Docker 部署方案 V1(全新安装 / 迁移 / 重装)

dlm
dlm
2026-03-29 / 0 评论 / 0 点赞 / 11 阅读 / 34225 字
温馨提示:
本文最后更新于 2026-03-29,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

OpenClaw Docker 接管实战教程:基于真实迁移成功案例,从旧环境迁移、重装到全新安装一步步跑通

摘要

这是一篇按“照着一步步做就能复现本次成功安装结果”标准整理的实战教程。它不讲虚的,也不假装所有问题都已经被彻底固化,而是基于这次真实跑通、真实验收成功的路径,把 ClawPanel + OpenClaw Gateway 在 Docker 中的 V1 可用方案完整写出来。

本文会明确拆成两条线路:

  1. 全新安装线路:适合新机器、新目录、从零起步部署的人。
  2. 重装 / 迁移线路:适合已经有旧 ClawPanel / OpenClaw 环境、想把数据切换到宿主机 bind mount、同时保留原记忆、插件、会话和配置的人。

两条线路都会逐步写清楚:

  • 每一步要做什么
  • 为什么要这样做
  • 要执行的完整命令
  • 要创建或修改的完整文件内容
  • 每一步执行后应该看到什么
  • 如果结果不对,优先怎么排查

本文记录的是本次已经真实跑通的成功路径。它的重点是:

  • 成功切换到宿主机 bind mount 数据目录
  • clawpanel 正常运行
  • openclaw-gateway 正常运行
  • gateway /health 正常返回
  • webchat 可继续使用
  • 微信插件启动链正常

同时也要提前讲清楚:

  • 这篇文章写的是当前已经验证成功的方案,不是假装所有后续固化工作都已经完成
  • 当前 gateway 依然是运行时在线安装 OpenClaw CLI
  • 后续如果还有进一步固化方案,应另外写新文章补充,而不是把未验证完成的内容硬塞进本文

导航

  • 一、这篇文章最终要达到什么结果
  • 二、先讲清楚:这套 V1 方案到底解决了什么
  • 三、部署前准备:无论新装还是重装,都先把这些前提确认清楚
  • 四、方案 A:全新安装(从空目录开始)
  • 五、方案 B:已有旧环境,重装 / 迁移到 bind mount
  • 六、部署完成后的最终验收清单
  • 七、常见故障与优先排查顺序
  • 八、这套 V1 方案当前的边界
  • 九、最终总结

目录


一、这篇文章最终要达到什么结果

按本文操作完成后,你应当能达到下面这组结果:

  1. Docker 项目根目录固定在: /opt/clawpanel-all-in-one

  2. OpenClaw 持久化数据根目录固定在: /opt/clawpanel-all-in-one/data/openclaw

  3. docker compose ps 应看到:

    • clawpanel -> Up
    • openclaw-gateway -> Up (healthy)
  4. 执行以下健康检查命令:

    curl http://127.0.0.1:18789/health
    

    应返回:

    {"ok":true,"status":"live"}
    
  5. 宿主机可以直接看到 OpenClaw 关键数据,例如:

    • workspace/
    • workspace/MEMORY.md
    • workspace/memory/
    • extensions/
    • agents/
    • openclaw.json
  6. Web 端可以继续对话

  7. 微信插件启动链正常,不再依赖“数据全藏在 Docker volume 黑盒里”的旧状态


二、先讲清楚:这套 V1 方案到底解决了什么

这次工程里,真正被解决掉的,不是“某次侥幸启动成功”,而是下面这些关键问题:

1. 数据从 Docker volume 黑盒,切到宿主机 bind mount 可见目录

以前最麻烦的问题之一,是 OpenClaw 核心数据主要躺在 Docker volume 里。只要一涉及:

  • 备份
  • 排障
  • 迁移
  • 查会话
  • 查插件
  • 查记忆文件

就很容易变成“先猜 volume 在哪里”。

这次成功路径里,已经把核心数据切到了宿主机可直接查看的目录:

/opt/clawpanel-all-in-one/data/openclaw

这意味着:

  • 记忆文件能直接看
  • 工作区能直接看
  • 插件目录能直接看
  • agent 会话能直接看
  • openclaw.json 能直接看
  • 做备份、迁移、排障时,不再先从 volume 黑盒猜起

2. gateway 启动命令已经验证了正确姿势

本次实战已经明确验证:

正确命令:

openclaw gateway

不要再用:

openclaw gateway start
openclaw gateway start --foreground

之前出过一次大坑,就是 compose 里把 gateway 启动命令写成了 openclaw gateway start --foreground,结果当前版本根本不认,直接把链路搞废。

所以本文后面所有正式写法,都以:

openclaw gateway

为唯一正确前台运行方式。

3. healthcheck 已切到 Node 脚本,不再依赖 curl 假告警

之前还有一个很烦的坑:

  • 容器明明其实已经起来了
  • docker compose ps 里却显示 unhealthy
  • 根因不是 gateway 真挂了,而是 healthcheck 用了 curl
  • node:22-slim 镜像里不一定有 curl

所以这次成功方案里,healthcheck 改成了:

healthcheck:
  test: ["CMD", "node", "/healthcheck/gateway-healthcheck.js"]

对应脚本是:

/opt/clawpanel-all-in-one/runtime/gateway-healthcheck.js

这样就不会再被“curl 不存在”这种低级问题污染健康状态判断。

4. 这篇文章是 V1,不是假装 V2 已完成

这一点必须说清楚,免得误导别人。

本篇写的是:

  • 已经跑通的真实方案
  • 当前可长期使用的 V1 稳定方案

但它还不是:

  • 独立 Dockerfile.gateway 固化镜像终版
  • 完全不依赖运行时在线安装 CLI 的终极版本

当前 V1 的 gateway 仍然是用下面这种启动逻辑:

npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com && \
  openclaw init 2>/dev/null || true && \
  openclaw gateway

这套逻辑已经被这次实际部署验证为可用,因此 V1 可以发。

未来如果把 gateway 再进一步固化成更干净的镜像方案,那是后续 V2 的内容,不在本文里冒充已经完成。


三、部署前准备:无论新装还是重装,都先把这些前提确认清楚

这一节不要跳。尤其是第一次部署的人,最容易因为“看起来简单”直接跳过去,最后自己把自己坑了。

3.1 机器与系统前提

本文默认你使用的是一台 Linux 服务器,并且:

  1. 你有 root 权限,或者有等价的 sudo 权限
  2. 系统已经安装好 Docker
  3. 系统已经安装好 Docker Compose 插件(即 docker compose 可用)
  4. 你能正常访问公网 npm 源,或者能访问文中使用的镜像源
  5. 你允许把项目根目录放在: /opt/clawpanel-all-in-one

3.2 先检查 Docker 是否可用

执行下面两条命令:

docker --version
docker compose version

预期结果

两条命令都应该正常输出版本号,例如:

Docker version 27.x.x, build xxxxx
Docker Compose version v2.x.x

如果不对怎么办

  • 如果 docker --version 报错:先安装 Docker
  • 如果 docker compose version 报错:先安装 Docker Compose 插件
  • 这两项没准备好,后面的内容不要继续

3.3 本文统一使用的目录结构

本文统一使用:

/opt/clawpanel-all-in-one/
├── Dockerfile.clawpanel
├── docker-compose.yml
├── runtime/
│   └── gateway-healthcheck.js
├── scripts/
│   ├── backup-pre-reinstall.sh
│   ├── migrate-openclaw-data.sh
│   └── verify-openclaw.sh
└── data/
    └── openclaw/

各目录的作用

  • /opt/clawpanel-all-in-one/
    • 项目总根目录
  • /opt/clawpanel-all-in-one/data/openclaw/
    • OpenClaw 的持久化数据目录
  • /opt/clawpanel-all-in-one/runtime/
    • 放运行时辅助脚本,例如 healthcheck
  • /opt/clawpanel-all-in-one/scripts/
    • 放备份、迁移、验收等运维脚本

3.4 当前 V1 的核心思路

本文不是“两个容器都自己维护自己的数据”。

当前 V1 的核心设计是:

  • clawpanel 使用项目内构建出来的镜像
  • openclaw-gateway 使用 node:22-slim
  • gateway 启动时在线安装 @qingchencloud/openclaw-zh
  • 两个容器都把 /root/.openclaw 挂到宿主机同一个目录: /opt/clawpanel-all-in-one/data/openclaw

这样做的直接结果是:

  • 数据统一
  • 宿主机可见
  • backup / migrate / verify 的逻辑统一
  • 当前这轮真实成功结果可复现

四、方案 A:全新安装(从空目录开始)

这一节适合:

  • 新服务器
  • 新目录
  • 之前没有现成旧环境
  • 或者你明确接受从零开始搭一套新的结构

A-1. 创建项目目录

这一步的目的

在宿主机上创建统一的部署根目录和子目录,后面所有文件都放这里,不要边做边换地方。

要执行的命令

mkdir -p /opt/clawpanel-all-in-one
mkdir -p /opt/clawpanel-all-in-one/runtime
mkdir -p /opt/clawpanel-all-in-one/scripts
mkdir -p /opt/clawpanel-all-in-one/data/openclaw
cd /opt/clawpanel-all-in-one
pwd

预期结果

最后一条 pwd 应输出:

/opt/clawpanel-all-in-one

如果不对怎么办

  • 如果提示权限不足,请使用 root 或 sudo
  • 如果你不打算用本文的固定路径,就不要继续照抄本文,后面所有路径都得跟着改

A-2. 创建 Dockerfile.clawpanel

这一步的目的

构建 clawpanel 容器镜像。当前这次成功方案里,clawpanel 侧使用的是单独 Dockerfile。

要执行的命令

cat > /opt/clawpanel-all-in-one/Dockerfile.clawpanel <<'EOF'
FROM node:22-slim

RUN apt-get update && apt-get install -y python3 git ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN git clone https://github.com/qingchencloud/clawpanel.git . && npm install

RUN npm run build

EXPOSE 1420

CMD ["npm", "run", "serve"]
EOF

写完后立即检查文件内容

执行:

sed -n '1,200p' /opt/clawpanel-all-in-one/Dockerfile.clawpanel

你应该看到的完整内容

FROM node:22-slim

RUN apt-get update && apt-get install -y python3 git ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN git clone https://github.com/qingchencloud/clawpanel.git . && npm install

RUN npm run build

EXPOSE 1420

CMD ["npm", "run", "serve"]

如果不对怎么办

  • 如果文件里混进了 shell 提示符、额外空行、命令本身文字,说明你粘贴脏了,删掉重写
  • 如果 sed 看不到完整内容,先别继续 build

A-3. 创建 gateway Node healthcheck 脚本

这一步的目的

openclaw-gateway 提供一个不依赖 curl 的健康检查脚本,避免 node:22-slim 环境里因为缺少 curl 导致误报 unhealthy

要执行的命令

cat > /opt/clawpanel-all-in-one/runtime/gateway-healthcheck.js <<'EOF'
const url = 'http://127.0.0.1:18789/health';

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 4000);

fetch(url, { signal: controller.signal })
  .then(async (res) => {
    clearTimeout(timeout);
    const text = await res.text();
    if (!res.ok) {
      console.error(`healthcheck failed: status=${res.status} body=${text}`);
      process.exit(1);
    }
    process.stdout.write(text);
    process.exit(0);
  })
  .catch((err) => {
    clearTimeout(timeout);
    console.error(`healthcheck error: ${err.message}`);
    process.exit(1);
  });
EOF

写完后立即检查

sed -n '1,200p' /opt/clawpanel-all-in-one/runtime/gateway-healthcheck.js

你应该看到的完整内容

const url = 'http://127.0.0.1:18789/health';

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 4000);

fetch(url, { signal: controller.signal })
  .then(async (res) => {
    clearTimeout(timeout);
    const text = await res.text();
    if (!res.ok) {
      console.error(`healthcheck failed: status=${res.status} body=${text}`);
      process.exit(1);
    }
    process.stdout.write(text);
    process.exit(0);
  })
  .catch((err) => {
    clearTimeout(timeout);
    console.error(`healthcheck error: ${err.message}`);
    process.exit(1);
  });

如果不对怎么办

  • 少一行都别往下走
  • fetchAbortControllerprocess.exit 这些关键逻辑不要擅自改

A-4. 创建验收脚本 scripts/verify-openclaw.sh

这一步的目的

把部署后的检查固定成一个脚本,不要每次靠肉眼想“我该查什么”。

要执行的命令

cat > /opt/clawpanel-all-in-one/scripts/verify-openclaw.sh <<'EOF'
#!/usr/bin/env bash
set -eu

cd /opt/clawpanel-all-in-one

echo "==> [1/4] docker compose ps"
docker compose ps

echo
echo "==> [2/4] gateway /health"
HEALTH_OUTPUT="$(curl -fsS http://127.0.0.1:18789/health)"
echo "$HEALTH_OUTPUT"

if [ "$HEALTH_OUTPUT" != '{"ok":true,"status":"live"}' ]; then
  echo "❌ gateway /health 返回异常"
  exit 1
fi

echo
echo "==> [3/4] data/openclaw top level"
find /opt/clawpanel-all-in-one/data/openclaw -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'

echo
echo "==> [4/4] done"
echo "✅ 基础巡检通过:compose / health / data 目录均已检查"
EOF

赋予执行权限

chmod +x /opt/clawpanel-all-in-one/scripts/verify-openclaw.sh

检查文件内容

sed -n '1,200p' /opt/clawpanel-all-in-one/scripts/verify-openclaw.sh

你应该看到的完整内容

#!/usr/bin/env bash
set -eu

cd /opt/clawpanel-all-in-one

echo "==> [1/4] docker compose ps"
docker compose ps

echo
echo "==> [2/4] gateway /health"
HEALTH_OUTPUT="$(curl -fsS http://127.0.0.1:18789/health)"
echo "$HEALTH_OUTPUT"

if [ "$HEALTH_OUTPUT" != '{"ok":true,"status":"live"}' ]; then
  echo "❌ gateway /health 返回异常"
  exit 1
fi

echo
echo "==> [3/4] data/openclaw top level"
find /opt/clawpanel-all-in-one/data/openclaw -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'

echo
echo "==> [4/4] done"
echo "✅ 基础巡检通过:compose / health / data 目录均已检查"

说明

这个 V1 验收脚本做的是“基础验收”,重点检查:

  • compose 状态
  • gateway /health
  • bind mount 数据目录

如果你后面还要加更复杂的插件状态检查,可以在这个脚本基础上继续增强。但本文先保证当前真实成功基线能复现。


A-5. 创建迁移脚本 scripts/migrate-openclaw-data.sh

这一步的目的

即使你现在是全新安装,也建议把迁移脚本先放好。这样后面如果要从旧 volume 导数据,脚本已经在位。

要执行的命令

cat > /opt/clawpanel-all-in-one/scripts/migrate-openclaw-data.sh <<'EOF'
#!/usr/bin/env bash
set -eu

OLD_VOLUME="${1:-clawpanel-all-in-one_openclaw-data}"
TARGET_DIR="/opt/clawpanel-all-in-one/data/openclaw"

mkdir -p "$TARGET_DIR"

echo "==> source volume: $OLD_VOLUME"
echo "==> target dir   : $TARGET_DIR"

docker run --rm \
  -v "$OLD_VOLUME":/from \
  -v "$TARGET_DIR":/to \
  alpine:3.20 \
  sh -c 'cd /from && cp -a . /to/'

echo "✅ migration copy finished"
EOF

赋予执行权限

chmod +x /opt/clawpanel-all-in-one/scripts/migrate-openclaw-data.sh

立即检查

sed -n '1,200p' /opt/clawpanel-all-in-one/scripts/migrate-openclaw-data.sh

A-6. 创建重装前备份脚本 scripts/backup-pre-reinstall.sh

这一步的目的

把重装前备份动作固定下来,避免真正到重装那一步时才手忙脚乱。

要执行的命令

cat > /opt/clawpanel-all-in-one/scripts/backup-pre-reinstall.sh <<'EOF'
#!/usr/bin/env bash
set -eu

TS="$(date -u +%Y%m%dT%H%M%SZ)"
BACKUP_ROOT="/opt/clawpanel-all-in-one/backup/pre-reinstall-$TS"
mkdir -p "$BACKUP_ROOT"

if [ -f /opt/clawpanel-all-in-one/docker-compose.yml ]; then
  cp -a /opt/clawpanel-all-in-one/docker-compose.yml "$BACKUP_ROOT/"
fi

if [ -f /opt/clawpanel-all-in-one/Dockerfile.clawpanel ]; then
  cp -a /opt/clawpanel-all-in-one/Dockerfile.clawpanel "$BACKUP_ROOT/"
fi

if [ -d /opt/clawpanel-all-in-one/runtime ]; then
  cp -a /opt/clawpanel-all-in-one/runtime "$BACKUP_ROOT/"
fi

if [ -d /opt/clawpanel-all-in-one/scripts ]; then
  cp -a /opt/clawpanel-all-in-one/scripts "$BACKUP_ROOT/"
fi

if [ -d /opt/clawpanel-all-in-one/data/openclaw ]; then
  tar -C /opt/clawpanel-all-in-one/data -czf "$BACKUP_ROOT/openclaw-data.tar.gz" openclaw
fi

echo "✅ backup done: $BACKUP_ROOT"
EOF

赋予执行权限

chmod +x /opt/clawpanel-all-in-one/scripts/backup-pre-reinstall.sh

立即检查

sed -n '1,220p' /opt/clawpanel-all-in-one/scripts/backup-pre-reinstall.sh

A-7. 创建 docker-compose.yml

这一步的目的

把整个部署结构写死下来:

  • clawpanel 单独 build
  • openclaw-gateway 使用 node:22-slim
  • /root/.openclaw 统一挂到宿主机 bind mount
  • healthcheck 使用 Node 脚本
  • gateway 使用已验证正确的前台命令 openclaw gateway

要执行的命令

cat > /opt/clawpanel-all-in-one/docker-compose.yml <<'EOF'
services:
  gateway:
    image: node:22-slim
    container_name: openclaw-gateway
    restart: unless-stopped
    working_dir: /root
    command: >
      sh -c "npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com &&
      openclaw init 2>/dev/null || true &&
      openclaw gateway"
    ports:
      - "18789:18789"
    volumes:
      - ./data/openclaw:/root/.openclaw
      - ./runtime/gateway-healthcheck.js:/healthcheck/gateway-healthcheck.js:ro
    healthcheck:
      test: ["CMD", "node", "/healthcheck/gateway-healthcheck.js"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 40s

  clawpanel:
    build:
      context: .
      dockerfile: Dockerfile.clawpanel
    container_name: clawpanel
    restart: unless-stopped
    working_dir: /app
    ports:
      - "1420:1420"
    volumes:
      - ./data/openclaw:/root/.openclaw
    environment:
      NODE_ENV: production
    depends_on:
      gateway:
        condition: service_healthy
EOF

写完后立即检查

sed -n '1,240p' /opt/clawpanel-all-in-one/docker-compose.yml

你应该看到的完整内容

services:
  gateway:
    image: node:22-slim
    container_name: openclaw-gateway
    restart: unless-stopped
    working_dir: /root
    command: >
      sh -c "npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com &&
      openclaw init 2>/dev/null || true &&
      openclaw gateway"
    ports:
      - "18789:18789"
    volumes:
      - ./data/openclaw:/root/.openclaw
      - ./runtime/gateway-healthcheck.js:/healthcheck/gateway-healthcheck.js:ro
    healthcheck:
      test: ["CMD", "node", "/healthcheck/gateway-healthcheck.js"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 40s

  clawpanel:
    build:
      context: .
      dockerfile: Dockerfile.clawpanel
    container_name: clawpanel
    restart: unless-stopped
    working_dir: /app
    ports:
      - "1420:1420"
    volumes:
      - ./data/openclaw:/root/.openclaw
    environment:
      NODE_ENV: production
    depends_on:
      gateway:
        condition: service_healthy

这一步特别注意

不要把 gateway command 写成:

openclaw gateway start

也不要写成:

openclaw gateway start --foreground

这两个都不是本次成功路径。


A-8. 构建并启动服务

这一步的目的

正式把 clawpanelopenclaw-gateway 拉起来。

要执行的命令

cd /opt/clawpanel-all-in-one
docker compose up -d --build

第一次启动时要有心理准备

第一次启动通常会比普通容器慢,原因包括:

  • clawpanel 要 build
  • gateway 首次启动时会在线安装 @qingchencloud/openclaw-zh
  • 健康检查要等服务真正起来后才会转绿

查看启动过程

建议马上执行:

docker compose ps
docker compose logs --tail=100 gateway
docker compose logs --tail=100 clawpanel

预期结果

你最终应看到:

  • gateway 容器存在
  • clawpanel 容器存在
  • gateway 日志里出现类似:
    • heartbeat started
    • health-monitor started
    • listening on ws://127.0.0.1:18789
  • clawpanel 日志里出现类似:
    • ClawPanel Web Server (Headless)
    • http://0.0.0.0:1420/

如果不对怎么办

  1. 如果 gateway 容器反复退出: 先查 docker compose logs gateway
  2. 如果看到和 openclaw gateway start --foreground 有关的报错: 说明你命令写错了
  3. 如果 clawpanel 没起来: 查 docker compose logs clawpanel
  4. 如果 gateway 长时间 starting: 多半是 CLI 在线安装还没跑完,先别急着判死刑

A-9. 基础验收

这一步的目的

确认整个结构已经真正跑起来,而不是“看起来大概差不多”。

先跑验收脚本

cd /opt/clawpanel-all-in-one
./scripts/verify-openclaw.sh

再手工补两条关键检查

docker compose ps
curl -fsS http://127.0.0.1:18789/health

预期结果

  1. docker compose ps 里看到:
    • clawpanel -> Up
    • openclaw-gateway -> Up (healthy)
  2. curl -fsS http://127.0.0.1:18789/health 返回:
{"ok":true,"status":"live"}

再检查宿主机数据目录

find /opt/clawpanel-all-in-one/data/openclaw -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'

预期结果

你应该能在宿主机上直接看到 /root/.openclaw 的映射内容,而不是一个空目录。

在全新安装场景下,一开始内容可能还不多,但目录至少不该完全没有 OpenClaw 运行痕迹。


五、方案 B:已有旧环境,重装 / 迁移到 bind mount

这一节是本文最重要的部分之一。

它适合下面这些场景:

  • 你之前已经跑过 ClawPanel / OpenClaw
  • 数据还在旧 Docker volume 里
  • 你不想丢失记忆、插件、会话、配置
  • 你想把旧结构迁到宿主机 bind mount
  • 同时保留一个可回滚的旧保险

B-1. 先确认你现在是不是旧环境迁移场景

如果你满足下面任意一条,就优先走本节,而不是“当自己是新装”:

  • 旧环境里已经有记忆文件
  • 旧环境里已经登录过微信插件
  • 旧环境里已有 agent 会话记录
  • 旧环境里已经存在 openclaw.json
  • 你担心重装后数据丢失

只要你属于这些情况之一,就不要偷懒,不要跳过备份和卷名确认步骤。


B-2. 停掉当前服务

这一步的目的

在真正做迁移前,先停止旧容器,避免迁移时数据仍在被写入。

要执行的命令

cd /opt/clawpanel-all-in-one
docker compose down

预期结果

容器被停止并移除,但 volume 不会因为这一步自动删除。

注意

不要执行这种带卷删除的命令:

docker compose down -v

这条在没确认备份和迁移前,风险太高。


B-3. 确认真实旧 volume 名,不要想当然

这一步的目的

本次实战已经踩过坑:

真实旧卷名是:

clawpanel-all-in-one_openclaw-data

不是:

openclaw-data

但你在自己机器上仍然应该先确认,不要因为文章里写了一个名字,就直接拿去赌。

先列出本机 volume

docker volume ls

再定位当前项目实际使用的卷

docker inspect clawpanel --format '{{json .Mounts}}'
docker inspect openclaw-gateway --format '{{json .Mounts}}'

你应该重点看什么

看输出里是否出现:

  • Type: volume
  • 卷名接近 clawpanel-all-in-one_openclaw-data
  • 目标挂载路径是 /root/.openclaw

本次实战确认的结论

这次真实成功迁移里,旧卷名已实锤为:

clawpanel-all-in-one_openclaw-data

后面示例如果没特别说明,都按这个真实卷名演示。


B-4. 先做重装前备份

这一步的目的

在真正迁移前,先把当前 compose、脚本、运行目录和 bind mount 数据(如果已有)打一个时间戳备份。

要执行的命令

cd /opt/clawpanel-all-in-one
./scripts/backup-pre-reinstall.sh

预期结果

脚本应输出类似:

✅ backup done: /opt/clawpanel-all-in-one/backup/pre-reinstall-20260328T090000Z

备份完成后立即检查

find /opt/clawpanel-all-in-one/backup -maxdepth 2 -mindepth 1 | sort | tail -n 20

说明

即使你觉得“反正旧 volume 还在”,这一步也不要省。多一层保险总比真出事后哭强。


B-5. 创建 bind mount 目标目录

这一步的目的

为迁移后的宿主机数据目录做好承接位置。

要执行的命令

mkdir -p /opt/clawpanel-all-in-one/data/openclaw
ls -ld /opt/clawpanel-all-in-one/data/openclaw

预期结果

应能看到目录存在。

注意

  • 如果目录已经存在,不是问题
  • 真正危险的是:你以为存在,实际路径写错了

B-6. 把旧 volume 数据复制到宿主机 bind mount 目录

这一步的目的

把旧的 /root/.openclaw 数据从 Docker volume 拷出来,复制到宿主机目录 /opt/clawpanel-all-in-one/data/openclaw

要执行的命令

cd /opt/clawpanel-all-in-one
./scripts/migrate-openclaw-data.sh clawpanel-all-in-one_openclaw-data

如果你已经核对出自己机器的旧卷名不同

那就把最后一个参数替换成你实际查出来的卷名,不要死抄:

./scripts/migrate-openclaw-data.sh 你的真实旧卷名

预期结果

脚本应输出类似:

==> source volume: clawpanel-all-in-one_openclaw-data
==> target dir   : /opt/clawpanel-all-in-one/data/openclaw
✅ migration copy finished

迁移完成后立即检查目标目录

find /opt/clawpanel-all-in-one/data/openclaw -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'

你应该看到什么

至少应看到大量原本属于 /root/.openclaw 的数据,例如:

  • workspace/
  • extensions/
  • agents/
  • openclaw.json

如果目标目录还是空的怎么办

优先排查:

  1. 你传入的旧卷名是不是错了
  2. 旧容器真实挂载的卷名是不是另一个名字
  3. docker run -v 旧卷:/from ... 是否能实际读到内容

不要在这一步目录还是空的时候直接继续 up -d。那样很容易把“迁移失败”伪装成“新环境覆盖旧环境”。


B-7. 写入正式的 V1 docker-compose.yml

如果你前面已经按方案 A 写好了 docker-compose.yml,这里仍然建议再核对一遍,确保你真正用的是 bind mount 版本,而不是旧的 volume 版本。

再次确认 compose 文件中的关键行

执行:

grep -n "./data/openclaw:/root/.openclaw" /opt/clawpanel-all-in-one/docker-compose.yml
grep -n "gateway-healthcheck.js" /opt/clawpanel-all-in-one/docker-compose.yml
grep -n "openclaw gateway" /opt/clawpanel-all-in-one/docker-compose.yml

预期结果

应至少命中下面这些核心特征:

  • ./data/openclaw:/root/.openclaw
  • ./runtime/gateway-healthcheck.js:/healthcheck/gateway-healthcheck.js:ro
  • openclaw gateway

如果 grep 没命中怎么办

不要继续启动,先回去把 compose 改对。


B-8. 启动新结构

要执行的命令

cd /opt/clawpanel-all-in-one
docker compose up -d --build

启动后立刻看状态

docker compose ps
docker compose logs --tail=100 gateway
docker compose logs --tail=100 clawpanel

预期结果

  1. gateway 起得来
  2. clawpanel 起得来
  3. gateway 后续应转为 healthy
  4. 旧数据应被新结构正确使用,而不是变成一套空白的新环境

B-9. 验证旧数据确实被新结构接住了

要执行的命令

./scripts/verify-openclaw.sh

再补充执行:

find /opt/clawpanel-all-in-one/data/openclaw/workspace -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'
find /opt/clawpanel-all-in-one/data/openclaw/extensions -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'
find /opt/clawpanel-all-in-one/data/openclaw/agents -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'
ls -l /opt/clawpanel-all-in-one/data/openclaw/openclaw.json

预期结果

你应该在宿主机上直接看到:

  • 原来的工作区文件
  • 记忆文件
  • 扩展插件目录
  • agent 会话目录
  • openclaw.json

这一步如果成立,才说明本次迁移真正成功了。


B-10. 保留旧 volume,不要急着删

这一步的目的

给自己留回滚锚点。

本次实战的明确结论

旧 volume:

clawpanel-all-in-one_openclaw-data

目前建议保留,不要删。

为什么不要删

因为新 bind mount 结构虽然已经实测跑通,但观察期内保留旧卷,能给你这些保障:

  • 万一发现遗漏数据,还能回查
  • 万一新结构后面又出问题,还有额外保险
  • 可以做二次离线导出

当前建议

至少等新结构稳定运行一段时间后,再考虑是否清理旧卷。


六、部署完成后的最终验收清单

这一节无论是新装还是重装,都必须做。

6.1 容器状态验收

执行:

cd /opt/clawpanel-all-in-one
docker compose ps

通过标准

应该看到:

  • clawpanel -> Up
  • openclaw-gateway -> Up (healthy)

如果 gateway 不是 healthy,先别自我安慰说“应该没事”,先往下查。

6.2 gateway 健康检查验收

执行:

curl -fsS http://127.0.0.1:18789/health

通过标准

必须返回:

{"ok":true,"status":"live"}

6.3 gateway 日志特征验收

执行:

docker compose logs --tail=200 gateway

通过标准

应能看到类似信号:

  • heartbeat started
  • health-monitor started
  • agent model:
  • listening on ws://127.0.0.1:18789
  • openclaw-weixin 相关启动日志
  • weixin monitor started

6.4 clawpanel 日志特征验收

执行:

docker compose logs --tail=200 clawpanel

通过标准

应能看到类似:

  • ClawPanel Web Server (Headless)
  • http://0.0.0.0:1420/
  • 配置目录: /root/.openclaw

6.5 数据目录验收

执行:

find /opt/clawpanel-all-in-one/data/openclaw -maxdepth 2 -mindepth 1 | sort | sed -n '1,120p'

通过标准

宿主机上应能直接看到 OpenClaw 关键数据,而不是空目录。

重装场景里尤其要确认:

  • workspace/
  • workspace/MEMORY.md
  • workspace/memory/
  • extensions/
  • agents/
  • openclaw.json

6.6 业务侧验收

最后再做人类视角的业务验收:

  1. 打开 webchat,看是否能正常对话
  2. 检查微信插件是否正常工作
  3. 检查原有记忆 / 配置 / 会话是否仍可继续使用

这一步不能省,因为“容器起来了”不等于“业务真的可用了”。


七、常见故障与优先排查顺序

7.1 gateway 显示 unhealthy

先执行:

docker compose ps
docker compose logs --tail=200 gateway
curl -fsS http://127.0.0.1:18789/health

怎么判断

  • 如果 /health 已经返回 {"ok":true,"status":"live"} 但 compose 仍显示 unhealthy 才去怀疑 healthcheck 本身
  • 但本文这套 V1 已经把 healthcheck 切到 Node 脚本,正常情况下不该再因为 curl 缺失误报

7.2 gateway 启动失败

先看 compose 里是不是把命令写错了。

正确:

openclaw gateway

错误:

openclaw gateway start
openclaw gateway start --foreground

这两个错误命令不要再碰。

7.3 迁移后 data/openclaw 还是空的

优先怀疑:

  • 旧卷名写错
  • 没有先 inspect 真实挂载
  • 复制时其实没从正确的卷里读到数据

本次实战的关键坑就是:

  • 真正旧卷是 clawpanel-all-in-one_openclaw-data
  • 不是很多人会想当然写的 openclaw-data

7.4 重装后看起来像全新环境

这通常意味着:

  • bind mount 目录没接到原数据
  • 或者你启动时绑定的是一个空目录

不要继续盲目登录、盲目初始化,先查宿主机 data/openclaw 里到底有没有旧数据。


八、这套 V1 方案当前的边界

本文是当前真实成功路径的完整沉淀,但也要诚实说清边界:

  1. 当前 gateway 仍是运行时在线安装 CLI,不是最终镜像固化版
  2. 本文解决的是“本次真实可复现成功路径”,不是宣称未来所有版本、所有插件行为永远不变
  3. 首次接入外部平台(例如某些插件登录、扫码、授权)仍可能需要人工参与
  4. 如果你未来要继续追求更强固化,下一步方向应是:
    • 评估单独 Dockerfile.gateway
    • 在镜像构建阶段预装 OpenClaw CLI
    • 进一步减少运行时在线安装依赖

但这些属于 V2,不是本文要硬塞进去假装已经做完的内容。


九、最终总结

如果你要的是一篇:

  • 不省关键步骤
  • 区分新装和重装
  • 命令能直接抄
  • 文件内容完整给出
  • 能按步骤复现本次真实成功结果
  • 并且能把数据切到宿主机 bind mount、让 webchat / gateway / 微信插件链路继续正常工作的教程

那么本文这版 V1,就是当前应该使用的版本。

最后把最关键的事实再压一遍:

当前 V1 成功基线

  • 项目根目录: /opt/clawpanel-all-in-one
  • 数据根目录: /opt/clawpanel-all-in-one/data/openclaw
  • gateway 正确命令: openclaw gateway
  • healthcheck: Node 脚本,不用 curl 探测
  • 旧卷真实名字: clawpanel-all-in-one_openclaw-data
  • 旧卷当前建议: 先保留,不要急着删

当前推荐的日常检查顺序

cd /opt/clawpanel-all-in-one
./scripts/verify-openclaw.sh

如果还要再补:

docker compose ps
curl -fsS http://127.0.0.1:18789/health

做到这里,你就不是“这次凑巧跑通”,而是已经把一套可复现、可排查、可回滚、可继续维护的 V1 路线真正搭起来了。


标签建议

  • OpenClaw
  • ClawPanel
  • Docker
  • Docker Compose
  • 微信插件
  • 部署教程
  • 运维实战
  • 数据迁移

SEO 描述

这是一篇基于真实成功路径整理的 ClawPanel + OpenClaw Gateway Docker 一体化部署实战教程,完整覆盖全新安装、旧环境重装迁移、bind mount 数据切换、gateway 健康检查、验收脚本与常见故障排查,适合希望按步骤复现可用状态的新手用户。

0

评论区