Docker 部署 OpenClaw:搭建只对本机开放的个人 AI 助手
OpenClaw 把模型、聊天渠道、工具、Skills、定时任务和会话状态统一放在一个 Gateway 后面。适合 Docker 的场景通常是一台长期在线的个人主机:浏览器从本机进入 Control UI,Telegram、Discord 等渠道按需连接,配置与工作区跟随数据目录持久化。
部署版本为 OpenClaw v2026.7.1-2,官方镜像支持 Linux amd64 和 arm64。下方 Compose 已完成静态解析;当前环境未拉取镜像、未启动容器,也没有执行模型或聊天渠道验收。
部署结论
| 项目 | 本文采用的值 |
|---|---|
| GitHub 地址 | openclaw/openclaw |
| 官方镜像 | ghcr.io/openclaw/openclaw:2026.7.1-2 |
| 项目版本 | v2026.7.1-2 |
| 正式部署 | Docker Compose,两项服务分别承担 Gateway 与 CLI |
| 快速体验 | 不提供 docker run:首次 onboarding、Token、三类挂载和 CLI 共享网络缺一不可 |
| 适用范围 | 单用户、单机自托管;不是对抗性多租户平台 |
| 主机架构 | Linux amd64、arm64 |
| 最低资源 | 官方仅要求源码构建至少 2 GB 内存;预构建镜像没有单独给出资源下限 |
| 对外端口 | 宿主机 127.0.0.1:18789 -> Gateway 18789 |
| 持久化位置 | /opt/openclaw/state、workspace、auth-profile-secrets |
| 依赖服务 | 无必需数据库或缓存;至少需要一个可用模型提供方 |
| 验证范围 | 官方文档与 Compose 静态检查;未运行容器 |
| 部署日期 | 2026-08-28 |
官方 scripts/docker/setup.sh 能完成权限修正、交互式 onboarding 和 Compose 启动,默认却会把多个端口发布到宿主机所有网卡。下面保留官方两服务结构和初始化顺序,只发布 Control UI/Gateway 需要的 18789,并把宿主机监听收紧到 127.0.0.1。需要从其他设备访问时,优先使用 SSH 隧道或 Tailscale,不要直接开放公网端口。
运行结构
openclaw-gateway 保存会话、模型认证、渠道配置和工具策略,并提供 Control UI、HTTP 健康端点与 Gateway WebSocket。openclaw-cli 复用 Gateway 的网络命名空间,因此 CLI 能通过容器内的 127.0.0.1 管理同一实例。三个宿主机目录分别保存状态、工作区和 OAuth 认证资料的本地加密密钥。
正在准备渲染...
查看源码
flowchart LR
Browser[本机浏览器] -->|127.0.0.1:18789| Gateway[openclaw-gateway]
CLI[openclaw-cli] -->|共享网络命名空间| Gateway
Gateway --> Model[模型提供方]
Gateway --> Channels[Telegram / Discord / 其他渠道]
Gateway --> State[(state)]
Gateway --> Workspace[(workspace)]
Gateway --> Auth[(auth-profile-secrets)]基础部署不开启 agents.defaults.sandbox。容器化 Gateway 与 Agent 工具沙箱是两层不同机制;后者需要在 Gateway 容器中安装 Docker CLI 并挂载宿主机 Docker socket,权限范围明显扩大,不能当成默认选项。
部署前准备
目标主机需要 Docker Engine 或 Docker Desktop,以及 Docker Compose v2:
docker --version
docker compose version确认本机端口没有被占用:
ss -lntp | grep ':18789' || true准备 OpenClaw 数据目录。官方镜像以 UID/GID 1000:1000 的 node 用户运行,Linux bind mount 应预先交给该用户:
sudo install -d -m 0700 -o 1000 -g 1000 \
/opt/openclaw/state \
/opt/openclaw/workspace \
/opt/openclaw/auth-profile-secrets
sudo install -d -m 0755 -o "$(id -u)" -g "$(id -g)" /opt/openclaw
cd /opt/openclaw后一条命令只调整 /opt/openclaw 目录本身,不会改写三个数据目录的所有者。
Docker Compose 正式部署
生成 Token 与环境文件
Gateway Token 等价于这个 OpenClaw 实例的操作员凭据。命令在本机生成 32 字节随机值,并用 0600 权限保存:
cd /opt/openclaw
umask 077
OPENCLAW_GATEWAY_TOKEN="$(openssl rand -hex 32)"
{
printf '%s\n' \
'OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:2026.7.1-2@sha256:8789721d2e9b24b780a1504b56deb4c6bd5c7dbf96a1dd117e7c45c2ed72c8ac' \
'OPENCLAW_CONFIG_DIR=/opt/openclaw/state' \
'OPENCLAW_WORKSPACE_DIR=/opt/openclaw/workspace' \
'OPENCLAW_AUTH_PROFILE_SECRET_DIR=/opt/openclaw/auth-profile-secrets' \
'OPENCLAW_GATEWAY_PORT=18789' \
'OPENCLAW_GATEWAY_BIND=lan' \
'OPENCLAW_DISABLE_BONJOUR=1' \
'OPENCLAW_TZ=Asia/Shanghai'
printf 'OPENCLAW_GATEWAY_TOKEN=%s\n' "$OPENCLAW_GATEWAY_TOKEN"
} > .env
unset OPENCLAW_GATEWAY_TOKEN
chmod 600 .envOPENCLAW_GATEWAY_BIND=lan 指的是容器内部监听。宿主机仍由下面的 Compose 限制在 127.0.0.1,两者不能互换;如果容器内部使用 loopback,Docker bridge 发布的端口将无法到达 Gateway。
写入 Compose 配置
保存为 /opt/openclaw/compose.yaml:
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE}
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
OPENCLAW_DISABLE_BONJOUR: ${OPENCLAW_DISABLE_BONJOUR:-1}
TZ: ${OPENCLAW_TZ:-UTC}
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR}:/home/node/.config/openclaw
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
extra_hosts:
- host.docker.internal:host-gateway
ports:
- 127.0.0.1:${OPENCLAW_GATEWAY_PORT:-18789}:18789
init: true
restart: unless-stopped
command:
- node
- dist/index.js
- gateway
- --bind
- ${OPENCLAW_GATEWAY_BIND:-lan}
- --port
- "18789"
healthcheck:
test:
- CMD
- node
- -e
- fetch('http://127.0.0.1:18789/healthz').then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
openclaw-cli:
image: ${OPENCLAW_IMAGE}
network_mode: service:openclaw-gateway
env_file:
- .env
environment:
HOME: /home/node
OPENCLAW_HOME: /home/node
TERM: xterm-256color
OPENCLAW_STATE_DIR: /home/node/.openclaw
OPENCLAW_CONFIG_PATH: /home/node/.openclaw/openclaw.json
OPENCLAW_CONFIG_DIR: /home/node/.openclaw
OPENCLAW_WORKSPACE_DIR: /home/node/.openclaw/workspace
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
BROWSER: echo
TZ: ${OPENCLAW_TZ:-UTC}
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
- ${OPENCLAW_AUTH_PROFILE_SECRET_DIR}:/home/node/.config/openclaw
cap_drop:
- NET_RAW
- NET_ADMIN
security_opt:
- no-new-privileges:true
stdin_open: true
tty: true
init: true
entrypoint:
- node
- dist/index.js
depends_on:
- openclaw-gateway先解析最终配置,再拉取锁定镜像:
docker compose config --quiet
docker compose pullconfig --quiet 没有输出且退出码为 0 表示 Compose 结构通过。镜像较大,拉取时间取决于网络和磁盘;不要在拉取失败时改用来源不明的镜像站。
完成首次 onboarding
onboarding 会选择模型提供方、认证方式、默认模型、工作区和可选聊天渠道。Docker 负责常驻进程,所以不要在容器里安装 systemd/launchd daemon:
docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js onboard \
--mode local \
--no-install-daemon \
--gateway-auth token \
--gateway-token-ref-env OPENCLAW_GATEWAY_TOKEN \
--skip-ui \
--suppress-gateway-token-output无桌面的服务器选择 OAuth 时,会显示浏览器地址。用个人电脑完成登录后,把浏览器最终跳转到的完整 URL 粘贴回终端。不要把回调 URL、Gateway Token 或模型凭据发到聊天记录和工单。
把 Docker 运行模式和 Control UI 来源写入配置:
docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js config set --batch-json \
'[{"path":"gateway.mode","value":"local"},{"path":"gateway.bind","value":"lan"},{"path":"gateway.controlUi.allowedOrigins","value":["http://localhost:18789","http://127.0.0.1:18789"]}]'启动 Gateway:
docker compose up -d openclaw-gateway
docker compose psopenclaw-gateway 应先显示 Up,健康检查通过后显示 healthy。
验证部署结果
容器状态
docker compose psGateway 应处于 running/healthy;openclaw-cli 是按需启动的一次性服务,不需要常驻。
应用响应
curl -sS -o /dev/null -w 'healthz HTTP %{http_code}\n' \
http://127.0.0.1:18789/healthz
curl -sS -o /dev/null -w 'readyz HTTP %{http_code}\n' \
http://127.0.0.1:18789/readyz两个端点都返回 HTTP 200 才表示存活与就绪检查通过。浏览器随后打开 http://127.0.0.1:18789/,在 Settings 中填入 /opt/openclaw/.env 保存的 Gateway Token。
日志与深度健康检查
docker compose logs --tail=100 openclaw-gateway
docker compose exec openclaw-gateway sh -lc \
'node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN"'日志不应持续出现重启、认证失败或状态目录权限错误。深度检查会使用容器环境中的 Token,不需要把凭据展开到宿主机命令行参数。
持久化
先写入一个无敏感信息的工作区标记,再重建 Gateway 容器:
printf 'OpenClaw persistence check: %s\n' "$(date -Is)" \
| sudo tee /opt/openclaw/workspace/PERSISTENCE_CHECK.md >/dev/null
sudo chown 1000:1000 /opt/openclaw/workspace/PERSISTENCE_CHECK.md
docker compose up -d --force-recreate openclaw-gateway
docker compose exec openclaw-gateway \
test -f /home/node/.openclaw/workspace/PERSISTENCE_CHECK.md最后一条命令退出码为 0 只证明工作区挂载能跨容器重建保留。模型调用、聊天渠道、定时任务和备份恢复仍要分别验证。
首次使用
Control UI 能打开后,先在浏览器里发一条不调用工具的测试消息,确认默认模型认证有效。再运行配置检查:
docker compose run --rm openclaw-cli doctor --lint --json
docker compose run --rm openclaw-cli gateway status --deep --json聊天渠道不是基础部署的必需项。准备接入 Telegram、Discord 或 WhatsApp 时,优先使用 onboarding/configure 的交互流程,并保留默认的 DM pairing 或 allowlist;不要把 DM 策略直接改成 open。
日常运维
常用操作保持在 /opt/openclaw 目录执行:
docker compose ps
docker compose logs --tail=100 openclaw-gateway
docker compose restart openclaw-gateway
docker compose run --rm openclaw-cli plugins list --jsonrestart 不会拉取新镜像,也不会删除挂载目录。安装插件等价于向 Gateway 进程加入受信任代码,只安装明确审阅过且版本固定的插件。
备份与恢复
OpenClaw 的状态目录包含 openclaw.json、会话、SQLite 状态、插件和模型认证资料;工作区保存 Agent 文件;auth-profile-secrets 保存 OAuth 资料的本地加密密钥。三个目录与 .env 必须作为同一套备份处理。Docker 标准输出日志和容器内 /tmp/openclaw/ 的滚动日志不在这份归档中,需要单独接入宿主机日志轮转或集中采集。
为避免 SQLite 和会话文件在归档过程中继续写入,先停止 Gateway:
cd /opt/openclaw
sudo install -d -m 0700 /var/backups/openclaw
docker compose stop openclaw-gateway
BACKUP_FILE="/var/backups/openclaw/openclaw-$(date +%F-%H%M%S).tar.gz"
sudo tar -C /opt -czf "$BACKUP_FILE" \
openclaw/state \
openclaw/workspace \
openclaw/auth-profile-secrets \
openclaw/.env \
openclaw/compose.yaml
sudo chmod 600 "$BACKUP_FILE"
docker compose start openclaw-gateway
sudo tar -tzf "$BACKUP_FILE" | tail -n 20备份文件包含模型和 Gateway 凭据,应保持 root 所有、0600 权限,并复制到加密的异机存储。恢复前先保留当前目录,不要直接覆盖唯一副本:
cd /opt/openclaw
BACKUP_FILE="$(find /var/backups/openclaw -maxdepth 1 -type f \
-name 'openclaw-*.tar.gz' -print | sort | tail -n 1)"
test -n "$BACKUP_FILE"
sudo tar -tzf "$BACKUP_FILE" >/dev/null
docker compose stop openclaw-gateway
cd /opt
RESTORE_SUFFIX="$(date +%F-%H%M%S)"
sudo mv openclaw "openclaw.before-restore-${RESTORE_SUFFIX}"
sudo tar -xzf "$BACKUP_FILE" -C /opt
sudo chown -R 1000:1000 \
/opt/openclaw/state \
/opt/openclaw/workspace \
/opt/openclaw/auth-profile-secrets
cd /opt/openclaw
docker compose up -d openclaw-gateway
curl -fsS http://127.0.0.1:18789/readyz命令按时间戳选择最新归档并先检查目录结构。确认 Control UI、模型认证和一条历史会话都可读取后,再决定是否保留 openclaw.before-restore-*。
升级与回滚
升级前完成上述一致性备份,并在 OpenClaw Releases 与 GHCR 中确认目标 tag、digest 和平台。然后修改 .env 的 OPENCLAW_IMAGE,继续使用 tag@sha256:digest 形式:
cd /opt/openclaw
docker compose config --quiet
docker compose pull
docker compose up -d openclaw-gateway
curl -fsS http://127.0.0.1:18789/readyz
docker compose logs --tail=100 openclaw-gateway新镜像启动时会执行安全升级迁移与插件收敛;无法安全完成时,Gateway 会退出而不是报告健康。遇到持续重启时,使用同一套挂载运行修复:
docker compose run --rm --no-deps --entrypoint node openclaw-gateway \
dist/index.js doctor --fix
docker compose up -d openclaw-gateway不要假设旧镜像能读取升级后的状态。回滚优先恢复升级前的完整备份,再把 .env 和状态目录一起回到旧版本;只改回镜像 tag 可能遇到不可逆的数据或插件迁移。
安全边界
- Gateway Token 是共享操作员凭据,不是低权限 API key。任何持有者都应视为这个实例的受信任操作员。
- OpenClaw 的官方信任模型是一名受信任用户对应一个 Gateway。互不信任的用户应拆分到不同主机、VM 或至少不同 OS 用户与 Gateway,不能依靠 session ID 实现租户隔离。
- Compose 只把
18789绑定到宿主机回环地址。远程访问使用 SSH 隧道:ssh -N -L 18789:127.0.0.1:18789 user@gateway-host,或按官方说明配置 Tailscale Serve。 - 工具执行默认发生在 Gateway 环境。处理网页、邮件、附件等不可信内容时,应收紧工具 allowlist、执行审批和 DM/group allowlist;系统提示词不能替代这些硬边界。
- 基础 Compose 不挂载
/var/run/docker.sock。启用 Docker 工具沙箱会把宿主机 Docker 控制面带入信任范围,应使用官方 setup 脚本完成前置检查,不要手工把 socket 交给 Agent 容器。 - 插件与 Skills 属于受信任代码。固定版本、审阅来源,并限制能够修改
/opt/openclaw/state和工作区的本机账号。 .env、state、auth-profile-secrets 和备份都包含敏感资料,不能提交 Git、放入公开对象存储或粘贴到支持工单。
常见问题
浏览器无法打开 Control UI
先确认本机端口、健康状态和最近日志:
ss -lntp | grep ':18789'
curl -v http://127.0.0.1:18789/healthz
docker compose logs --tail=100 openclaw-gateway从另一台电脑直接访问失败是预期结果,因为 Compose 只监听宿主机 127.0.0.1。建立 SSH 隧道后,在客户端浏览器打开同一个本地地址。容器日志若显示 allowed origins 错误,重新执行 onboarding 后的 config set --batch-json 命令,不要关闭 Control UI 来源校验。
状态目录出现 EACCES
检查三个目录的数字所有者:
stat -c '%u:%g %a %n' \
/opt/openclaw/state \
/opt/openclaw/workspace \
/opt/openclaw/auth-profile-secrets官方镜像运行用户为 1000:1000。停止 Gateway 后修正目录所有权,再重新启动:
docker compose stop openclaw-gateway
sudo chown -R 1000:1000 \
/opt/openclaw/state \
/opt/openclaw/workspace \
/opt/openclaw/auth-profile-secrets
docker compose start openclaw-gateway不要把状态目录改成所有本机用户都可写;状态目录内包含认证资料。
OAuth 在无桌面服务器上无法回调
onboarding 输出登录地址后,用个人电脑浏览器完成授权。浏览器最终会跳转到本机回调地址,即使页面无法打开,地址栏里的完整 URL 仍包含 onboarding 所需结果;复制完整 URL 回终端即可。粘贴前确认终端正连接到可信主机,并避免共享终端录屏。
升级后 Gateway 持续重启
docker compose ps
docker compose logs --tail=200 openclaw-gateway日志如果明确要求配置或插件修复,使用“升级与回滚”中的 doctor --fix 一次性容器。修复仍失败时停止反复重启,恢复升级前备份;不要在不兼容状态上继续切换多个镜像版本。
部署完成后
- 在 Control UI 完成一条不调用工具的模型对话,再逐项开放必要工具。
- 为
/var/backups/openclaw设置加密异机备份与恢复演练,不只检查压缩包是否生成。 - 接入聊天渠道后保留 DM pairing/allowlist,并为处理不可信内容的 Agent 单独设计工具策略。
总结
OpenClaw v2026.7.1-2 通过官方 GHCR 镜像和两服务 Compose 运行 Gateway 与管理 CLI,Control UI 只监听宿主机回环地址。完成部署后应分别验证健康端点、模型认证、工作区持久化和备份恢复,而不是只看容器状态。
OpenClaw 以单用户受信任操作员为安全前提。Gateway Token、模型认证、工作区和插件都位于同一信任边界;公开端口、共享 Gateway 或挂载 Docker socket 会显著扩大影响范围。
参考资料
- OpenClaw 官方仓库 - 核对日期:2026-08-28
- OpenClaw v2026.7.1-2 Release - 采用版本:
v2026.7.1-2 - 官方 Docker 文档 - 核对 Compose、onboarding、健康端点、持久化和权限
- 官方 Compose - 核对服务、端口、卷、命令与健康检查
- 官方 Docker setup 脚本 - 核对 Token、权限修正、onboarding 与启动顺序
- OpenClaw GHCR - 核对
2026.7.1-2tag、manifest digest、amd64与arm64 - OpenClaw 安全策略 - 核对单用户信任模型、插件与公开暴露边界
- OpenClaw 更新文档 - 核对升级、doctor 与回滚约束