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 是保命符。
- 文件隔离 (Filesystem Isolation): 把它关在
/app里。它想rm -rf /?请便,删的只是容器里的文件,我的 Mac 毫发无损。 - 网络白名单 (Network Whitelist): 我们可以限制它只能访问特定的 API,防止它把我的本地数据传给不知名的服务器。
- 环境一致性: 你不用担心 Node.js 版本不对,或者缺了什么 Python 库。
手把手构建 “The Cage”
我们不需要什么花哨的 k8s,一个简单的 Dockerfile 和 docker-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 了。脚本跑完后,它会自动生成 .env,docker-compose.yml 和 docker-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” (网页爬虫)。
准备好唤醒它了吗?