名称: cloudflare-sandbox 描述: Cloudflare Sandboxes SDK 用于在边缘 Linux 容器中安全执行代码。适用于不受信任的代码、Python/Node.js 脚本、AI 代码解释器、git 操作。
关键词: cloudflare sandbox, container execution, code execution, isolated environment, durable objects, linux container, python execution, node execution, git operations, code interpreter, AI agents, session management, ephemeral container, workspace, sandbox SDK, @cloudflare/sandbox, exec(), getSandbox(), runCode(), gitCheckout(), ubuntu container 许可证: MIT
Cloudflare 沙箱 SDK
状态: 生产就绪(开放测试版)
最后更新: 2025-12-10
依赖项: cloudflare-worker-base, cloudflare-durable-objects(推荐用于理解)
最新版本: @cloudflare/sandbox@0.6.3, Docker 镜像: cloudflare/sandbox:0.6.3-python
⚠️ 重大变更 (v0.6.0): Python 不再包含在默认镜像中。使用 cloudflare/sandbox:<version>-python 获取 Python 支持(约 1.3GB,包含数据科学包)。精简版本(约 600-800MB)排除 Python。
快速开始(15 分钟)
1. 安装 SDK 并设置 Wrangler
bun add @cloudflare/sandbox@latest # 推荐
# 或: bun add @cloudflare/sandbox@latest
wrangler.jsonc:
{
"name": "my-sandbox-worker",
"main": "src/index.ts",
"compatibility_flags": ["nodejs_compat"],
"containers": [{
"class_name": "Sandbox",
"image": "cloudflare/sandbox:0.6.3-python",
"instance_type": "lite"
}],
"durable_objects": {
"bindings": [{
"class_name": "Sandbox",
"name": "Sandbox"
}]
},
"migrations": [{
"tag": "v1",
"new_sqlite_classes": ["Sandbox"]
}]
}
为什么重要:
nodejs_compat启用 SDK 所需的 Node.js APIcontainers定义 Ubuntu 容器镜像durable_objects绑定启用持久路由migrations注册 Sandbox 类
2. 创建您的第一个沙箱 Worker
import { getSandbox, type Sandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
type Env = {
Sandbox: DurableObjectNamespace<Sandbox>;
};
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// 获取沙箱实例(如果不存在则创建)
const sandbox = getSandbox(env.Sandbox, 'my-first-sandbox');
// 执行 Python 代码
const result = await sandbox.exec('python3 -c "print(2 + 2)"');
return Response.json({
output: result.stdout,
success: result.success,
exitCode: result.exitCode
});
}
};
关键:
- 必须导出
{ Sandbox }从@cloudflare/sandbox在您的 Worker 中 - 沙箱 ID 确定路由(相同 ID = 相同容器)
- 第一个请求创建容器(约 2-3 分钟冷启动)
- 后续请求快速(<1秒)
3. 部署并测试
npm run deploy
curl https://your-worker.workers.dev
预期输出:
{
"output": "4
",
"success": true,
"exitCode": 0
}
架构(理解三层模型)
沙箱如何工作
┌─────────────────────────────────────────┐
│ 您的 Worker(第 1 层) │
│ - 处理 HTTP 请求 │
│ - 调用 getSandbox() │
│ - 使用 sandbox.exec(), writeFile(), 等 │
└──────────────┬──────────────────────────┘
│ 通过 Durable Object 的 RPC
┌──────────────▼──────────────────────────┐
│ Durable Object(第 2 层) │
│ - 按沙箱 ID 路由 │
│ - 维护持久身份 │
│ - 地理粘性 │
└──────────────┬──────────────────────────┘
│ 容器 API
┌──────────────▼──────────────────────────┐
│ Ubuntu 容器(第 3 层) │
│ - 完整的 Linux 环境 │
│ - Python 3.11, Node 20, Git, 等 │
│ - 文件系统: /workspace, /tmp, /home │
│ - 进程隔离(基于 VM) │
└─────────────────────────────────────────┘
关键见解: Workers 处理 API 逻辑(快速),Durable Objects 路由请求(持久身份),Containers 执行代码(完整能力)。
关键容器生命周期(最重要部分!)
容器状态
┌─────────┐ 第一个请求 ┌────────┐ ~10 分钟空闲 ┌──────┐
│ 未创建 │ ────────────>│ 活跃 │ ─────────────> │ 空闲 │
│ │ │ │ │ │
└─────────┘ └───┬────┘ └──┬───┘
│ ^ │
│ │ 新请求 │
│ └──────────────────────┘
│ │
▼ ▼
文件持久化 所有文件删除
进程运行 所有进程终止
状态维护 所有状态重置
最大陷阱:默认为短暂性
当容器活跃时(约 10 分钟最后请求后):
- ✅ 文件在
/workspace,/tmp,/home持久化 - ✅ 后台进程继续运行
- ✅ Shell 环境变量保持
- ✅ 会话工作目录保留
当容器空闲时(空闲后):
- ❌ 所有文件删除(整个文件系统重置)
- ❌ 所有进程终止
- ❌ 所有 shell 状态丢失
- ⚠️ 下一个请求创建 从头开始的新容器
这不像传统服务器。沙箱设计为短暂性。
处理持久性
对于重要数据: 使用外部存储
// 在容器空闲前保存到 R2
await sandbox.writeFile('/workspace/data.txt', content);
const fileData = await sandbox.readFile('/workspace/data.txt');
await env.R2.put('backup/data.txt', fileData);
// 在下个请求恢复
const restored = await env.R2.get('backup/data.txt');
if (restored) {
await sandbox.writeFile('/workspace/data.txt', await restored.text());
}
对于构建工件: 接受短暂性或使用缓存
// 检查是否需要设置(处理冷启动)
const exists = await sandbox.readdir('/workspace/project').catch(() => null);
if (!exists) {
await sandbox.gitCheckout(repoUrl, '/workspace/project');
await sandbox.exec('npm install', { cwd: '/workspace/project' });
}
// 现在安全运行构建
await sandbox.exec('npm run build', { cwd: '/workspace/project' });
会话管理(聊天代理的游戏改变者)
什么是会话?
会话是 bash shell 上下文 在一个沙箱内。想象终端标签。
关键属性:
- 每个会话有独立的工作目录
- 会话共享相同的文件系统
- 工作目录在同一会话中的命令间持久化
- 完美适用于多步工作流
模式:基于聊天的编码代理
type ConversationState = {
sandboxId: string;
sessionId: string;
};
// 第一条消息:创建沙箱和会话
const sandboxId = `user-${userId}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
const sessionId = await sandbox.createSession();
// 存储在对话状态(数据库、KV 等)
await env.KV.put(`conversation:${conversationId}`, JSON.stringify({
sandboxId,
sessionId
}));
// 后续消息:重用相同会话
const state = await env.KV.get(`conversation:${conversationId}`);
const { sandboxId, sessionId } = JSON.parse(state);
const sandbox = getSandbox(env.Sandbox, sandboxId);
// 命令在相同上下文中运行
await sandbox.exec('cd /workspace/project', { session: sessionId });
await sandbox.exec('ls -la', { session: sessionId }); // 仍在 /workspace/project
await sandbox.exec('git status', { session: sessionId }); // 仍在 /workspace/project
无会话(常见错误)
// ❌ 错误:每个命令在独立会话中运行
await sandbox.exec('cd /workspace/project');
await sandbox.exec('ls'); // 不在 /workspace/project(不同会话)
模式:并行执行
const session1 = await sandbox.createSession();
const session2 = await sandbox.createSession();
// 同时运行不同任务
await Promise.all([
sandbox.exec('python train_model.py', { session: session1 }),
sandbox.exec('node generate_reports.js', { session: session2 })
]);
沙箱命名策略
每用户沙箱(持久工作区)
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);
优点: 用户工作在使用时持久(10 分钟空闲时间) 缺点: 地理锁定(第一个请求确定位置) 用例: 交互式笔记本、IDE、持久工作区
每会话沙箱(每次新鲜)
const sandboxId = `session-${Date.now()}-${crypto.randomUUID()}`;
const sandbox = getSandbox(env.Sandbox, sandboxId);
// 使用后始终销毁
await sandbox.destroy();
优点: 清洁环境,无状态污染 缺点: 请求间无持久性 用例: 一次性代码执行、CI/CD、测试
每任务沙箱(幂等且可追溯)
const sandbox = getSandbox(env.Sandbox, `build-${repoName}-${commitSha}`);
优点: 可重现、可调试、可缓存 缺点: 需要显式清理策略 用例: 构建系统、数据管道、自动化工作流
核心 API 参考
沙箱 SDK 提供命令执行、文件操作、Git 操作、代码解释(类似 Jupyter)、后台进程和清理的方法。
📖 加载 references/api-reference.md 当您需要详细的 API 方法签名、参数选项或实现示例时:
- 执行命令与选项(cwd、超时、环境变量、会话)
- 文件操作(读/写/mkdir/rm/readdir)
- Git 操作(gitCheckout, git 命令)
- 代码解释器(createCodeContext, runCode)
- 后台进程(spawn, isProcessRunning, killProcess)
- 沙箱清理(destroy)
关键规则
始终做
✅ 检查退出代码 - if (!result.success) { 处理错误 }
✅ 使用会话进行多步工作流 - 保留工作目录
✅ 处理冷启动 - 在假设文件存在前检查是否存在
✅ 设置超时 - 防止长时间操作挂起
✅ 销毁短暂沙箱 - 清理临时/基于会话的沙箱
✅ 使用外部存储进行持久性 - R2/KV/D1 用于重要数据
✅ 验证用户输入 - 在执行前消毒以防止命令注入
✅ 导出 Sandbox 类 - export { Sandbox } from '@cloudflare/sandbox'
永远不做
❌ 假设文件空闲后持久 - 容器约 10 分钟后重置
❌ 忽略退出代码 - 始终检查 result.success 或 result.exitCode
❌ 无会话链接命令 - cd /dir 然后 ls 无效
❌ 执行未消毒的用户输入 - 使用代码解释器或彻底验证
❌ 忘记 nodejs_compat 标志 - wrangler.jsonc 中必需
❌ 跳过迁移 - Durable Objects 需要迁移条目
❌ 使用 .workers.dev 用于预览 URL - 需要自定义域
❌ 创建无限沙箱 - 销毁短暂沙箱以避免泄漏
已知问题预防
此技能预防 10 个文档问题:
问题 #1: 缺少 nodejs_compat 标志
错误: ReferenceError: fetch is not defined 或 Buffer is not defined
来源: https://developers.cloudflare.com/sandbox/get-started/
原因: SDK 需要标准 Workers 中不可用的 Node.js API
预防: 在 wrangler.jsonc 中添加 "compatibility_flags": ["nodejs_compat"]
问题 #2: 缺少迁移
错误: Error: Class 'Sandbox' not found
来源: https://developers.cloudflare.com/durable-objects/
原因: Durable Objects 必须通过迁移注册
预防: 在 wrangler.jsonc 中包含迁移数组
问题 #3: 假设文件持久性
错误: 文件在空闲后消失 来源: https://developers.cloudflare.com/sandbox/concepts/sandboxes/ 原因: 容器约 10 分钟后空闲,所有状态重置 预防: 使用外部存储(R2/KV)或每个请求检查存在性
问题 #4: 会话目录混淆
错误: 命令在错误目录执行
来源: https://developers.cloudflare.com/sandbox/concepts/sessions/
原因: 每个 exec() 使用新会话除非明确指定
预防: 使用 createSession() 创建会话,传递给所有相关命令
问题 #5: 忽略退出代码
错误: 假设命令成功时失败
来源: Shell 最佳实践
原因: 未检查 result.success 或 result.exitCode
预防: 始终检查: if (!result.success) throw new Error(result.stderr)
问题 #6: 不处理冷启动
错误: 命令失败因为依赖未安装 来源: https://developers.cloudflare.com/sandbox/concepts/sandboxes/ 原因: 容器在空闲期后重置 预防: 在运行命令前检查是否需要设置
问题 #7: Docker 未运行(本地开发)
错误: Failed to build container 在本地开发期间
来源: https://developers.cloudflare.com/sandbox/get-started/
原因: 本地开发需要 Docker 守护进程
预防: 确保 Docker Desktop 在 npm run dev 前运行
问题 #8: 版本不匹配(包 vs Docker 镜像)
错误: API 方法不可用或行为意外
来源: GitHub 问题
原因: npm 包版本与 Docker 镜像版本不匹配
预防: 保持 @cloudflare/sandbox 包和 cloudflare/sandbox 镜像同步
问题 #9: 不清理短暂沙箱
错误: 资源耗尽,意外成本
来源: 资源管理最佳实践
原因: 创建沙箱而不销毁它们
预防: 在 finally 块中 await sandbox.destroy() 用于临时沙箱
问题 #10: 命令注入漏洞
错误: 从未消毒用户输入的安全漏洞
来源: 安全最佳实践
原因: 传递用户输入直接到 exec()
预防: 使用代码解释器 API 或彻底验证/消毒输入
wrangler.jsonc 示例
{
"name": "my-sandbox-app",
"main": "src/index.ts",
"compatibility_date": "2025-10-29",
"compatibility_flags": ["nodejs_compat"], // ← 必需
"containers": [{
"class_name": "Sandbox",
"image": "cloudflare/sandbox:0.6.3-python", // ← 使用 -python 获取 Python 支持
"instance_type": "lite"
}],
"durable_objects": {
"bindings": [{"class_name": "Sandbox", "name": "Sandbox"}]
},
"migrations": [{
"tag": "v1",
"new_sqlite_classes": ["Sandbox"]
}]
}
常见模式
四种生产就绪模式,用于使用 Cloudflare 沙箱构建:一次性代码执行、持久用户工作区、CI/CD 管道和 AI 代理集成。
📖 加载 references/patterns.md 当您需要完整的实现示例时:
- 一次性代码执行 - API 端点、代码游乐场、学习平台
- 持久用户工作区 - 交互式环境、笔记本、IDE
- CI/CD 构建管道 - 构建系统、测试管道、部署自动化
- AI 代理与 Claude 代码 - 自动化重构、代码生成、AI 开发
使用捆绑资源
脚本(scripts/)
setup-sandbox-binding.sh- 交互式 wrangler.jsonc 配置test-sandbox.ts- 验证脚本以测试沙箱设置
示例用法:
# 设置 wrangler 配置
./scripts/setup-sandbox-binding.sh
# 测试沙箱
bunx tsx scripts/test-sandbox.ts
参考(references/)
references/persistence-guide.md- 深入探讨容器生命周期和持久性references/session-management.md- 高级会话模式和最佳实践references/common-errors.md- 完整错误列表与解决方案references/naming-strategies.md- 为不同用例选择沙箱 ID
当 Claude 应该加载这些时:
- 加载
persistence-guide.md当调试状态问题或冷启动时 - 加载
session-management.md当构建多步工作流或聊天代理时 - 加载
common-errors.md当遇到特定错误时 - 加载
naming-strategies.md当设计沙箱架构时
高级主题
📖 加载 references/advanced.md 用于生产模式:
- 全球应用的地理分布策略
- 错误处理包装函数
- 安全加固和输入验证
官方资源
包: @cloudflare/sandbox@0.6.3 | Docker: cloudflare/sandbox:0.6.3-python
文档: Cloudflare 沙箱 | API 参考 | GitHub SDK