ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker 沙盒实战:给 OpenClaw 套上隔离层,API 密钥不再“裸奔”

Docker 沙盒实战:给 OpenClaw 套上隔离层,API 密钥不再“裸奔” 1. 本地跑 OpenClaw密钥为什么总在“裸奔”OpenClaw 是今年开源圈里跑得最快的 AI 编码代理之一它能在你本机直接读写文件、执行 Shell、发起网络请求一条指令就能让 AI 帮你改 Bug、跑测试、提交代码。方便是真方便但风险也藏在这份“自由”里它默认继承你当前用户的环境变量而ANTHROPIC_API_KEY、OPENAI_API_KEY这类密钥通常就写在.env或 shell profile 里。代理一旦被提示注入、被恶意仓库里的脚本诱导或者只是单纯地“理解错了任务”它完全有能力把密钥读出来、发到外部地址。我试过在本地直接跑 OpenClaw第一次看到它自动cat .env去确认配置时后背是有点发凉的。这不是 OpenClaw 的 bug而是所有本地 AI 代理的共性它需要密钥才能调用大模型但密钥一旦进入它的进程空间就不再受你控制。Docker 官方给出的思路很直接——把 OpenClaw 关进沙盒让密钥由代理层注入代理进程本身永远拿不到明文。这篇就按这个思路给你一套可复制的 Dockerfile 与 docker-compose 骨架并演示密钥注入和沙盒逃逸验证目标是你照着做就能跑起一套“密钥不落地”的 OpenClaw 环境。2. 前置准备TaoToken 与 Docker 环境2.1 为什么这里会用到 TaoTokenOpenClaw 本身只是个代理框架真正干活的是背后的大模型。你可以选择本地 Model Runner 跑开源模型也可以接云端 API 获得更强的编码能力。接云端时密钥管理就是核心问题。TaoToken 提供统一的模型接入层你可以在它的控制台生成 API Key然后在沙盒里通过环境变量注入OpenClaw 进程只拿到一个指向本地代理的地址密钥原文不进入容器。具体来说TaoToken 的 API 端点是https://taotoken.net/api兼容 OpenAI 风格的调用方式。你需要在控制台创建一个 Key后面我们会把它写进宿主机的.env再由 docker-compose 注入到沙盒的代理层而不是直接塞给 OpenClaw。2.2 Docker 环境要求你需要 Docker Desktop 24 以上版本并且开启 Sandboxes 支持目前主要在 macOS 和 Linux 的 Docker Desktop 中可用。如果你只是用普通容器做隔离也可以但 microVM 级别的内核隔离会更彻底。先确认版本docker version docker sandbox --help如果docker sandbox命令不存在说明你的 Docker Desktop 版本偏低升级到最新稳定版即可。另外本地至少留 8GB 内存给沙盒和模型推理编码代理跑起来后内存占用不低。2.3 目录结构规划我们在宿主机建一个工作目录把配置和密钥分开存放mkdir -p ~/openclaw-sandbox/{config,workspace,secrets} cd ~/openclaw-sandboxsecrets目录只放.env权限设为600并且不挂载进沙盒。workspace是 OpenClaw 唯一能读写的区域。config放 OpenClaw 的配置文件。3. 可复制配置Dockerfile 与 docker-compose 骨架3.1 Dockerfile构建带桥接脚本的 OpenClaw 镜像Docker 官方有预构建镜像olegselajev241/openclaw-dmr:latest但为了让你看清每一层我们手写一个精简版。核心是 Node.js 22、OpenClaw 本体以及一个把请求转发到沙盒网络代理的桥接脚本。FROM node:22-slim # 安装基础工具 RUN apt-get update apt-get install -y --no-install-recommends \ curl ca-certificates git \ rm -rf /var/lib/apt/lists/* # 安装 OpenClaw RUN npm install -g openclaw/cli # 创建非 root 用户降低逃逸后的破坏面 RUN useradd -m -s /bin/bash claw mkdir -p /workspace chown claw:claw /workspace # 桥接脚本把本地请求转发到沙盒网络代理 COPY bridge.js /usr/local/bin/bridge.js COPY start-openclaw.sh /usr/local/bin/start-openclaw.sh RUN chmod x /usr/local/bin/start-openclaw.sh USER claw WORKDIR /workspace ENTRYPOINT [/usr/local/bin/start-openclaw.sh]桥接脚本bridge.js的作用是监听127.0.0.1:54321把 OpenClaw 发出的请求转发到host.docker.internal:3128也就是沙盒的网络代理层。这样 OpenClaw 只能通过这条受控通路访问外部不能自己乱发请求。// bridge.js const http require(http); const { request } require(http); const PROXY_HOST host.docker.internal; const PROXY_PORT 3128; const LISTEN_PORT 54321; http.createServer((req, res) { const options { host: PROXY_HOST, port: PROXY_PORT, path: req.url, method: req.method, headers: { ...req.headers, host: ${PROXY_HOST}:${PROXY_PORT} }, }; const proxyReq request(options, (proxyRes) { res.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(res); }); proxyReq.on(error, (err) { res.writeHead(502); res.end(bridge error: ${err.message}); }); req.pipe(proxyReq); }).listen(LISTEN_PORT, 127.0.0.1, () { console.log(bridge listening on 127.0.0.1:${LISTEN_PORT}); });启动脚本start-openclaw.sh负责拉起桥接、设置 OpenClaw 的 API 地址指向桥接端口然后启动 OpenClaw#!/bin/bash set -e node /usr/local/bin/bridge.js sleep 1 export OPENCLAW_API_BASEhttp://127.0.0.1:54321/v1 export OPENCLAW_MODEL${OPENCLAW_MODEL:-claude-sonnet} exec openclaw $注意这里没有出现任何真实密钥OPENCLAW_API_BASE指向的是本地桥接桥接再走代理层。密钥由代理层在转发时注入。3.2 docker-compose密钥注入与网络隔离docker-compose 负责把宿主机.env里的密钥传给沙盒代理而不是传给 OpenClaw 容器本身。这里用env_file加载到代理服务OpenClaw 服务只拿到代理地址。version: 3.9 services: sandbox-proxy: image: alpine/socat:latest command: TCP-LISTEN:3128,fork,reuseaddr TCP:host.docker.internal:12434 environment: - ANTHROPIC_API_KEY${ANTHROPIC_API_KEY} - OPENAI_API_KEY${OPENAI_API_KEY} env_file: - ./secrets/.env networks: - claw-net openclaw: build: . depends_on: - sandbox-proxy volumes: - ./workspace:/workspace - ./config:/home/claw/.config/openclaw environment: - OPENCLAW_API_BASEhttp://sandbox-proxy:3128/v1 - OPENCLAW_MODELclaude-sonnet networks: - claw-net # 关键不挂载 secrets 目录不传密钥环境变量 read_only: false security_opt: - no-new-privileges:true networks: claw-net: driver: bridgesecrets/.env内容示例ANTHROPIC_API_KEYsk-ant-xxxxxxxx OPENAI_API_KEYsk-xxxxxxxx这个文件权限设为600只被sandbox-proxy读取。OpenClaw 容器里执行env是看不到这些 Key 的它只能看到OPENCLAW_API_BASE。4. 验证请求与沙盒逃逸测试4.1 启动并确认密钥不可见先构建并启动docker compose build docker compose up -d docker compose exec openclaw env | grep -i key预期输出为空或者只有OPENCLAW_API_BASE这类非敏感变量。如果你看到了ANTHROPIC_API_KEY说明注入路径写错了密钥泄漏到了代理进程。接着在 OpenClaw 容器里尝试读取宿主机文件docker compose exec openclaw cat /etc/shadow docker compose exec openclaw ls /home因为容器只挂载了workspace和config/etc/shadow会返回权限拒绝/home下也看不到宿主机的用户目录。这就是文件访问被硬限制在工作区的效果。4.2 验证模型调用通路在 OpenClaw 里发一个最小请求确认桥接和代理层工作正常docker compose exec openclaw curl -s http://127.0.0.1:54321/v1/models如果返回模型列表说明桥接把请求转发到了代理层代理层再路由到 TaoToken 或本地 Model Runner。你也可以直接在宿主机用 TaoToken 的 API 端点测试 Key 是否有效curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $ANTHROPIC_API_KEY注意这个命令在宿主机执行用的是宿主机环境变量和沙盒内的进程完全隔离。4.3 沙盒逃逸验证动作我们做两个轻量级验证确认边界有效。第一尝试从 OpenClaw 容器访问宿主机 localhost 的敏感端口docker compose exec openclaw curl -s --max-time 3 http://host.docker.internal:12434如果代理层没有放行这个端口请求会超时或被拒。第二尝试写入工作区之外docker compose exec openclaw touch /etc/test-escape预期返回Permission denied。这两个动作能让你直观看到OpenClaw 能碰到的只有你给它的那片空间。5. 本篇常见错排查5.1 桥接脚本报 502如果curl http://127.0.0.1:54321/v1/models返回 502先检查sandbox-proxy是否在运行docker compose ps docker compose logs sandbox-proxy常见原因是host.docker.internal在 Linux 上不自动解析需要在 compose 里加extra_hosts: - host.docker.internal:host-gateway5.2 密钥仍然出现在 OpenClaw 环境里检查docker-compose.yml里openclaw服务是否误加了env_file或environment里的 Key。密钥只能出现在sandbox-proxy服务。另外确认secrets目录没有被挂载进openclaw的 volumes。5.3 OpenClaw 启动后找不到模型如果 OpenClaw 报模型不存在检查OPENCLAW_MODEL是否和代理层实际提供的模型名一致。用 TaoToken 时模型名以控制台展示的为准用本地 Model Runner 时先docker model pull拉取对应模型再确认localhost:12434可访问。5.4 沙盒内 DNS 解析失败microVM 沙盒的网络默认走代理层如果代理层没有配置 DNS 转发容器内解析外部域名会失败。可以在sandbox-proxy里加dns配置或者直接用 IP 访问。更稳妥的做法是让代理层统一处理域名解析OpenClaw 只认桥接地址。5.5 工作区文件权限问题OpenClaw 以非 root 用户claw运行如果workspace目录在宿主机属于 root容器内会写不进去。启动前执行sudo chown -R 1000:1000 ~/openclaw-sandbox/workspace其中1000是容器内claw用户的 UID你可以用docker compose exec openclaw id确认。6. 把密钥关进代理层让 OpenClaw 只干活不碰钥匙这套方案的核心不是“信任 OpenClaw”而是给它设定可验证的边界文件访问限制在工作区网络请求经过代理层过滤API 密钥由代理层注入、代理进程不可见。你可以在 TaoToken 控制台生成和管理 API Key把 Key 写进宿主机的secrets/.env再通过 docker-compose 注入到sandbox-proxyOpenClaw 容器里始终只有一个指向桥接的地址。如果你需要长期跑编码代理或 Agent 工作流建议把镜像保存下来复用docker compose build docker save openclaw-sandbox_openclaw:latest -o openclaw-sandbox.tar团队成员拿到镜像后各自在宿主机配置自己的 TaoToken Key沙盒环境一致密钥互不干扰。需要更强模型能力时在 TaoToken 控制台切换模型即可OpenClaw 侧不用改任何配置。密钥不落地代理才敢放开跑。
返回列表