EP03 - 试图驯服一只猛兽:OpenClaw 的 Docker 监狱

昨天我在测试 OpenClaw 的 “File System Tool” 时,发生了一件让我冷汗直流的事。 我给它的指令是:“清理一下当前目录的临时文件”。 可能是因为我的 Prompt 写得太随意,它直接把我的整个 ~/Downloads 文件夹给清空了。

幸好那里只有一堆没用的安装包。但如果它删的是我的 ~/Documents 或者 .ssh 密钥呢?

这就是我们在 link:/posts/ai/why-i-choose-openclaw/[] 里提到的代价:强大的能力伴随着巨大的风险。 一个拥有 Shell 权限的 AI Agent,本质上就是一个盯着你键盘随时准备按下回车键的超级用户。在裸机 (Bare Metal) 上直接运行它,无异于把自家大门的钥匙交给一个喝醉了的锁匠。

今天,我们要给这个不仅聪明而且危险的家伙,造一座牢不可破的监狱。 这也是极客生存法则第一条:永远不要信任你的 Agent。

本文涉及本地Native安装的一些知识,你可以阅读上一篇 EP02 来了解它们。

为什么一定要用 Docker?

很多人觉得 Docker 只是为了方便部署。 错。对于 Agent 开发来说,Docker 是保命符

  1. 文件隔离 (Filesystem Isolation): 把它关在 /app 里。它想 rm -rf /?请便,删的只是容器里的文件,我的 Mac 毫发无损。
  2. 网络白名单 (Network Whitelist): 我们可以限制它只能访问特定的 API,防止它把我的本地数据传给不知名的服务器。
  3. 环境一致性: 你不用担心 Node.js 版本不对,或者缺了什么 Python 库。

手把手构建 “The Cage”

我们不需要什么花哨的 k8s,一个简单的 Dockerfiledocker-compose.yml 就够了。 但这里有几个针对 Mac 用户和 Ollama 的关键坑,我都替你踩平了。

1. 环境准备:你是新兵还是老鸟? (Pre-flight Check)

在开始构建之前,我们需要确认你的初始状态。

情况一:全新安装 (Fresh Install)

如果你从未在本机安装过 OpenClaw,请直接跳过此步,进入第 2 步。

情况二:老鸟迁移 (Migration from Native)

如果你的 Mac 上之前直接运行过 OpenClaw (Native模式),你的 ~/.openclaw 目录下会残留宿主机的绝对路径。这些路径直接挂载进 Docker 会导致权限错误 (EACCES: permission denied)。

在运行 Docker 之前,请务必执行以下清理动作

Action A: 修正配置文件路径 检查 ~/.openclaw/openclaw.json (或 config.json) 中的 agents.defaults.workspace 字段。 如果它是 /Users/...,必须改为容器路径:

 1{
 2  "agents": {
 3    "defaults": {
 4      // ❌ 错误 (宿主机路径):
 5      "workspace": "/Users/yourname/.openclaw/workspace",
 6      // ✅ 正确 (容器路径):
 7      "workspace": "/home/node/.openclaw/workspace"
 8    }
 9  }
10}

Action B: 清除旧缓存 (关键) 旧的 Session 记录里也缓存了宿主机路径,这会导致启动崩溃。最稳妥的方法是清除它们:

1# 别担心,这只会清除对话历史,配置都在
2rm -rf ~/.openclaw/agents

2. 官方推荐:懒人脚本 (The Script)

既然你已经 Clone 了源码 (git clone https://github.com/openclaw/openclaw.git),官方其实提供了一个非常完善的初始化脚本。它不仅配置了 Docker,还帮我们生成了必要的目录结构和鉴权 Token。

在项目根目录下运行:

1./docker-setup.sh

注意

下文中涉及到 docker compose 相关的命令,都需要在项目根目录下运行,因为需要 compose 文件的支持。

升级Bash版本

这里有一个大坑:macOS 自带的 Bash 版本停留在古老的 3.2 (2007年),不支持脚本中用到的高级特性 (关联数组)。运行如果报错 declare: -A: invalid option,请先升级 Bash:

1$ /usr/bin/env bash --version
2GNU bash, version 3.2.57(1)-release (arm64-apple-darwin24)
3Copyright (C) 2007 Free Software Foundation, Inc.
4# 升级bash版本
5brew install bash

升级之后,bash版本应该为 5.3, 再次运行脚本,现在应该可以顺利启动 docker 了。脚本跑完后,它会自动生成 .envdocker-compose.ymldocker-compose.extra.yml

脚本启动完成后,流程基本与本地安装一样,OpenClaw 会交互式地让你来配置, 如果你之前安装过,可能会直接使用旧的配置。不了解本地安装和配置的,可以看上一篇 EP02。

现在,你直接输入 docker ps 命令可以看到容器已经启动起来了。

如果你改错了 .openclaw 目录,没关系,你随时可以使用下边的命令重新来配置:

1docker compose run --rm openclaw-cli onboard

3. 首次启动与验证 (First Boot)

脚本跑完后,容器一般会自动启动起来。我们也可以手动启动,验证 Docker 环境是否正常。

启动服务:

1# 编译docker镜像
2docker build -t openclaw:local -f Dockerfile .
3# 启动交互式配置
4docker compose run --rm openclaw-cli onboard
5# 启动docker
6docker compose up -d openclaw-gateway

现在,浏览器访问: http://127.0.0.1:18789/, 成功打开,恭喜你,你的 OpenClaw 已经成功运行起来了。

你也可以通过终端来与 OpenClaw 交互:

1docker compose run --rm openclaw-cli tui --deliver

这里有一个坑

我尝试的版本(2026.1.29)有bug,tui连接时无视了我的配置,还尝试连接 127.0.0.1, gateway在docker中,当然无法连接,此时我们可以手动指定url即可:

1docker compose run --rm openclaw-cli tui --url http://host.docker.internal:18789 --deliver

4. (进阶) 构建真正的牢笼:Sandboxing

刚才的步骤只是把 OpenClaw 跑在了容器里。 但官方文档里有一个更硬核的特性:Gateway Sandboxing

你可能会问:“Docker 真的安全吗?” 答案是:相对安全,但不是绝对。如果容器内的进程以 root 权限运行,或者有特权逃逸漏洞,主机依然有风险。

OpenClaw 的 Sandboxing 是第二道防线。这意味着 Gateway 可以在执行某些高危任务(比如运行不信任的 Python/JS 代码)时,动态生成一个一次性、无网络、甚至只读的子容器来执行任务。

构建官方沙盒镜像

官方推荐使用专门的沙盒镜像 openclaw-sandbox:bookworm-slim,而不是通用的 node:alpine

在 OpenClaw 项目根目录下运行:

1# 构建基础沙盒镜像
2./scripts/sandbox-setup.sh
3
4# (可选) 如果需要更多工具(Python、Go、Rust、Homebrew 等)
5./scripts/sandbox-common-setup.sh

注意sandbox-common 镜像体积较大(包含完整开发环境),仅在需要时使用。

配置沙盒

在配置文件 ~/.openclaw/openclaw.json 中开启沙盒模式:

 1{
 2  "agents": {
 3    "defaults": {
 4      "sandbox": {
 5        "mode": "non-main", // off | non-main | all
 6        "scope": "agent", // agent | session | shared
 7        "workspaceAccess": "none", // none | ro | rw
 8        "docker": {
 9          "image": "openclaw-sandbox:bookworm-slim",
10          "workdir": "/workspace",
11          "network": "none", // 断网!绝对安全
12          "readOnlyRoot": true, // 禁止修改系统文件
13          "user": "1000:1000",
14          "capDrop": ["ALL"],
15          "memory": "1g",
16          "pidsLimit": 256
17        },
18        "prune": {
19          "idleHours": 24, // 空闲 24 小时后清理
20          "maxAgeDays": 7 // 最长存活 7 天
21        }
22      }
23    }
24  },
25  "tools": {
26    "sandbox": {
27      "tools": {
28        "allow": ["exec", "process", "read", "write", "edit"],
29        "deny": ["browser", "gateway", "discord"]
30      }
31    }
32  }
33}

关键配置说明

  • mode: "non-main": 除了主会话,其他工具都在沙盒运行
  • workspaceAccess: "none": 沙盒使用独立工作区 (~/.openclaw/sandboxes)
  • workspaceAccess: "ro": 沙盒可读取 Agent 工作区(禁止写入)
  • workspaceAccess: "rw": 沙盒直接使用 Agent 工作区(慎用)
  • prune: 自动清理长期闲置的沙盒容器

这才是真正的 “Cage”。即使 Agent 被提示词注入了,想运行恶意脚本挖矿,它发现自己在断网、只读、只有 1GB 内存的真空环境里,除了报错什么也干不了。

如果你修改了配置,记得重启服务:

1docker compose restart openclaw-gateway

5. 日常维护 (Daily Maintenance)

数据在哪里? Docker 里的数据(包括 Workspace 文件和 Agent 记忆)都通过 Volume 映射到了宿主机。

  • Workspace: ./workspace (项目根目录下)
  • 数据库/记忆: 默认在 Docker Volume 中,除非你修改了 .env 指定路径。

如何更新? 当 OpenClaw 发布新版本时,更新非常简单:

1# 拉取最新镜像
2docker compose pull
3# 重新创建并启动容器
4docker compose up -d

总结与预告

至此,我们已经成功构建了一个安全、隔离、易于维护的 OpenClaw 运行环境。 现在的它,虽然还在沉睡(没有连接大模型),但已经是一个合格的“躯壳”了。

Ep 04: 注入灵魂。 不管是 Docker 还是 Native,下一篇我们将把这个安全的躯壳与强大的 DeepSeek R1 大脑连接起来,并教它第一个实战技能:“Web Scraper” (网页爬虫)

准备好唤醒它了吗?


相关阅读