ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

skills 仓库精读:Cloudflare Sandbox 常用模式实战(AI 代码执行、交互式 IDE 与实时服务)

skills 仓库精读:Cloudflare Sandbox 常用模式实战(AI 代码执行、交互式 IDE 与实时服务) skills 仓库精读Cloudflare Sandbox 常用模式实战AI 代码执行、交互式 IDE 与实时服务【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills本文基于 skills 仓库中 Cloudflare Deploy Skill 的 Sandbox 参考文档 patterns.md 编写系统梳理在 Cloudflare 边缘容器沙箱中落地各类典型工作负载的八种常用模式。读者将掌握如何用createCodeContext搭建带持久上下文的 AI 代码执行器、如何用exposePort暴露交互式开发环境、如何通过 WebSocket 代理构建实时服务、如何用 R2 Bucket 挂载实现持久化数据以及如何把沙箱接入 CI/CD 流水线与多租户系统。所有模式均为可直接复制到 Worker 入口的 TypeScript 代码并补充了来自 api.md、configuration.md 与 gotchas.md 的底层 API、配置参数与陷阱说明。背景Sandbox 与常用模式的关系Cloudflare Sandbox SDK 提供在 Cloudflare 边缘的容器中安全隔离执行代码的能力每个沙箱本质上是Durable Object Container的组合见 sandbox README同一 ID 对应同一沙箱跨请求保持存活并拥有独立的文件系统、进程与网络空间。底层容器运行时细节可参考 containers 参考文档Durable Object 基础设施可参考 durable-objects 参考文档。模式文档将这些能力组织为八个可复用的工作负载模板。它们共享同一条关键骨架在 Worker 的fetch处理器中第一行必须调用proxyToSandbox(request, env)用于接管预览 URL 与 WebSocket 握手等代理流量随后用getSandbox(env.Sandbox, id)获取或创建沙箱。以下逐个展开。模式一带代码上下文的 AI 代码执行最常见的需求是给 AI Agent 一个能真正运行代码的沙箱。模式文档给出的做法是使用createCodeContext创建携带持久变量的代码上下文再通过ctx.runCode执行export default { async fetch(request: Request, env: Env): PromiseResponse { const { code, variables } await request.json(); const sandbox getSandbox(env.Sandbox, ai-agent); // Create context with persistent variables const ctx await sandbox.createCodeContext({ language: python, variables: variables || {} }); // Execute with rich outputs (text, images, HTML) const result await ctx.runCode(code); return Response.json({ outputs: result.outputs, // [{ type: text|image|html, content }] error: result.error, success: !result.error }); } };该模式对应 api.md 中的Code InterpreterAPIrunCode返回{ outputs: [{ type: text|image|html, content }], error }意味着一次执行可以同时产出文本、图像如 matplotlib 绘制的图表和 HTML非常适合 AI 数据分析场景。language指定解释器语言variables注入初始变量。需要特别强调的是上下文跨运行持久代码上下文中声明的变量会保留到下一次runCode见 api.md 中Context persists variables across runs的示例这使 Agent 可以分步执行先加载数据、再分析、再绘图的完整流程。但模式文档与 gotchas.md 同时提醒代码上下文是临时的容器重启sleep 后唤醒或重新调度会清空状态因此 Agent 需要在容器醒来后重建上下文而不是假设变量永远存在。模式二交互式开发环境云端 IDE沙箱不只是跑一次性命令还可以承载完整的开发环境。模式文档演示了如何按需启动 code-serverexport default { async fetch(request: Request, env: Env): PromiseResponse { const proxyResponse await proxyToSandbox(request, env); if (proxyResponse) return proxyResponse; const sandbox getSandbox(env.Sandbox, ide, { normalizeId: true }); if (request.url.endsWith(/start)) { await sandbox.exec(curl -fsSL https://code-server.dev/install.sh | sh); await sandbox.startProcess(code-server --bind-addr 0.0.0.0:8080, { processId: vscode }); const exposed await sandbox.exposePort(8080); return Response.json({ url: exposed.url }); } return new Response(Try /start); } };三个关键点normalizeId: true模式文档在此处显式开启。根据 configuration.md这是预览 URL 的前置条件ID 会被小写化从而影响 Durable Object 的哈希 ID见 gotchas.mdDifferent normalizeId different sandbox同时必须先把请求交给proxyToSandbox才能拿到可访问的预览地址。startProcess启动后台进程code-server 以processId: vscode标识为后台常驻进程对应 api.md 中的 Background Processes 体系——之后可用sandbox.getProcess(vscode)查询、sandbox.stopProcess(vscode)停止、sandbox.getProcessLogs(vscode)拉取日志。exposePort(8080)暴露端口返回{ url }即一个形如https://8080-sandbox-abc123def456.yourdomain.com的带令牌预览 URLgotchas.md 说明令牌在每次 expose 时轮换防止未授权访问。注意该模式没有waitForPort等待生产建议参考下面的进程就绪模式以确保 code-server 真正监听后再返回 URL。模式三WebSocket 实时服务对于聊天、协作编辑、终端流等实时场景Sandbox 提供wsConnect直接代理 WebSocketexport default { async fetch(request: Request, env: Env): PromiseResponse { const proxyResponse await proxyToSandbox(request, env); if (proxyResponse) return proxyResponse; if (request.headers.get(Upgrade)?.toLowerCase() websocket) { const sandbox getSandbox(env.Sandbox, realtime-service); return await sandbox.wsConnect(request, 8080); } // Non-WebSocket: expose preview URL const sandbox getSandbox(env.Sandbox, realtime-service); const { url } await sandbox.exposePort(8080, { hostname: new URL(request.url).hostname }); return Response.json({ wsUrl: url.replace(https, wss) }); } };配套 Dockerfile 需要在镜像中预装ws库并声明端口FROM docker.io/cloudflare/sandbox:latest RUN npm install -g ws EXPOSE 8080实现要点用Upgrade: websocket请求头区分握手请求代理到沙箱内 8080 端口的 WebSocket 服务与普通请求返回把https替换为wss的 WebSocket 地址。hostname选项用于在自定义域名场景下正确生成预览 URL——这是配置文档中Preview URL Setup一节强调的需要自定义域名 通配符 DNS*.yourdomain.com → worker.yourdomain.com.workers.dev域名不支持预览 URL。模式四进程就绪模式waitForPort后台服务最常见的坑是端口还没起来就暴露。模式文档给出了标准解法——startProcess之后用waitForPort等待端口监听export default { async fetch(request: Request, env: Env): PromiseResponse { const sandbox getSandbox(env.Sandbox, app-server); // Start server const process await sandbox.startProcess( node server.js, { processId: server } ); // Wait for server to be ready await process.waitForPort(8080); // Wait for port listening // Now safe to expose const { url } await sandbox.exposePort(8080); return Response.json({ url }); } };api.md 补充了另外两个等待原语process.waitForLog(/Server running/)按日志模式匹配就绪与process.waitForExit()等待进程结束按需选用。端口就绪超时由containerTimeouts.portReadyTimeoutMS控制默认 90000ms90 秒可通过SANDBOX_PORT_TIMEOUT_MS环境变量覆盖见 configuration.mdTimeout Environment Overrides。模式五R2 Bucket 挂载实现持久化数据沙箱的文件系统是临时的需要持久化数据时挂载 R2 Bucketexport default { async fetch(request: Request, env: Env): PromiseResponse { const sandbox getSandbox(env.Sandbox, data-processor); // Mount R2 bucket (production only) await sandbox.mountBucket(env.DATA_BUCKET, /data, { readOnly: false }); // Process files in bucket const result await sandbox.exec(python3 /workspace/process.py, { env: { DATA_DIR: /data/input } }); // Results written to /data/output are persisted in R2 return Response.json({ success: result.success }); } };挂载语义来自 api.md 与 gotchas.md仅生产环境可用Bucket 挂载依赖 FUSEwrangler dev本地开发不支持需在本地用 mock 数据测试沙箱级可见挂载的 Bucket 对同一沙箱内的所有 session 可见读写控制readOnly: false表示可写写入挂载目录的内容会持久化到 R2unmountBucket(/data)可解除挂载对应 wrangler 配置为r2_buckets绑定见 configuration.md例如{ binding: DATA_BUCKET, bucket_name: my-data-bucket }。这个模式特别适合数据批处理、ETL 与训练数据准备的场景容器无状态但通过 R2 获得无限且持久的存储。模式六CI/CD 流水线沙箱天然适合跑构建与测试——隔离、可销毁、按需创建export default { async fetch(request: Request, env: Env): PromiseResponse { const { repo, branch } await request.json(); const sandbox getSandbox(env.Sandbox, ci-${repo}-${Date.now()}); await sandbox.exec(git clone -b ${branch} ${repo} /workspace/repo); const install await sandbox.exec(npm install, { cwd: /workspace/repo, stream: true, onOutput: (stream, data) console.log(data) }); if (!install.success) { return Response.json({ success: false, error: Install failed }); } const test await sandbox.exec(npm test, { cwd: /workspace/repo }); return Response.json({ success: test.success, output: test.stdout, exitCode: test.exitCode }); } };要点ID 采用ci-${repo}-${Date.now()}每次 CI 运行生成唯一沙箱避免任务间互相污染。但从性能角度见 gotchas.mdSandbox ID Strategy对需要复用状态的场景应改用稳定 ID如按用户 ID因为创建新沙箱比唤醒已有沙箱慢得多stream: trueonOutput实时把子进程 stdout/stderr 流式转发到 Worker 日志适合长耗时安装步骤的进度观测cwd选项指定命令工作目录这里是/workspace/repoexec的返回值{ stdout, stderr, exitCode, success, duration }可直接映射为 CI 结果。注意生产 CI 中敏感令牌不要硬编码在 URL 里应通过env选项注入见Git 操作一节。模式七多租户隔离模式为每个用户提供独立会话是构建用户提交代码、云端执行类 SaaS 的标准做法export default { async fetch(request: Request, env: Env): PromiseResponse { const userId request.headers.get(X-User-ID); const sandbox getSandbox(env.Sandbox, multi-tenant); // Each user gets isolated session let session; try { session await sandbox.getSession(userId); } catch { session await sandbox.createSession({ id: userId, cwd: /workspace/users/${userId}, env: { USER_ID: userId } }); } const code await request.text(); const result await session.exec(python3 -c ${code}); return Response.json({ output: result.stdout }); } };api.md 说明 session 是隔离上下文每个 session 维护独立的 shell 状态、环境变量、cwd 与进程命名空间并可调用完整的沙箱 APIsession.exec、session.writeFile等。沙箱本身又是隔离的容器文件系统、网络、进程彼此独立沙箱之间无法直接通信见 gotchas.mdSandbox Isolation由此形成容器级隔离 会话级隔离的双层租户边界。不过模式文档这个示例把用户代码直接拼进 shell 命令python3 -c ${code}这是 gotchas.md 明确警告的命令注入风险。安全写法是写入文件再执行// ✅ SAFE: Write to file, execute file await session.writeFile(/workspace/user_code.py, code); const result await session.exec(python3 /workspace/user_code.py);模式八Git 操作沙箱内的 Git 操作有两种形态模式文档Git Operations节// Clone repo await sandbox.exec(git clone https://github.com/user/repo.git /workspace/repo); // Authenticated (use env secrets) await sandbox.exec(git clone https://${env.GITHUB_TOKEN}github.com/user/repo.git);认证克隆的实践要点来自 configuration.md 与 gotchas.md令牌从env.GITHUB_TOKEN读取由wrangler secret put GITHUB_TOKEN设置见 configuration.mdCLI Commands与Environment Secrets严禁硬编码传给沙箱内命令时通过exec的env选项注入而不是拼进命令行例如const token env.GITHUB_TOKEN; // From wrangler secret await sandbox.exec(git clone https://github.com/user/repo.git, { env: { GIT_TOKEN: token } });需要说明的是上述代码示例来自原文档其中将令牌直接拼接进 URL 的方式在生产中并非推荐做法更稳妥的是使用env注入后由仓库内脚本或 credential helper 消费避免令牌出现在进程命令行与日志中。八个模式共用的底层支撑Worker 入口与沙箱获取所有模式都遵循同一入口骨架见 sandbox READMEimport { getSandbox, proxyToSandbox, type Sandbox } from cloudflare/sandbox; export { Sandbox } from cloudflare/sandbox; type Env { Sandbox: DurableObjectNamespaceSandbox; }; export default { async fetch(request: Request, env: Env): PromiseResponse { const proxyResponse await proxyToSandbox(request, env); if (proxyResponse) return proxyResponse; const sandbox getSandbox(env.Sandbox, my-sandbox); const result await sandbox.exec(python3 -c print(2 2)); return Response.json({ output: result.stdout }); } };关键规则Critical RulesproxyToSandbox()必须最先调用否则预览 URL 与 WebSocket 代理不生效同一 ID 复用同一沙箱持久文件放在/workspace/tmp等路径的文件不持久见 gotchas.mdFile not persisting预览 URL 需normalizeId: true容器未就绪时报CONTAINER_NOT_READY需重试。wrangler.jsonc 容器与 DO 配置让上述代码跑起来需要完整的 wrangler 配置来自 READMEQuick Start{ name: my-sandbox-worker, main: src/index.ts, compatibility_date: 2025-01-01, // Use current date for new projects containers: [{ class_name: Sandbox, image: ./Dockerfile, instance_type: lite, // lite | standard | heavy max_instances: 5 }], durable_objects: { bindings: [{ class_name: Sandbox, name: Sandbox }] }, migrations: [{ tag: v1, new_sqlite_classes: [Sandbox] }] }配套 Dockerfile模式文档与 README 一致FROM docker.io/cloudflare/sandbox:latest RUN pip3 install --no-cache-dir pandas numpy matplotlib EXPOSE 8080 3000 # Required for wrangler devEXPOSE在wrangler dev下是必需的本地端口访问依赖它生产环境会自动暴露所有端口configuration.mdCRITICAL提示。实例类型三档可选lite256MB RAM / 0.5 vCPU默认、standard512MB / 1 vCPU、heavy1GB / 2 vCPU高流量场景调大max_instancesgotchas.md 示例为 50。getSandbox 的运行时选项模式文档虽未展开但各模式用到的选项语义都在 configuration.md 中整理如下const sandbox getSandbox(env.Sandbox, sandbox-id, { normalizeId: true, // lowercase ID (required for preview URLs) sleepAfter: 10m, // sleep after inactivity: 5m, 1h, 2d (default: 10m) keepAlive: false, // false auto-timeout, true never sleep containerTimeouts: { instanceGetTimeoutMS: 30000, // 30s for provisioning (default: 30000) portReadyTimeoutMS: 90000 // 90s for container startup (default: 90000) } });sleepAfter默认10m无活动后休眠休眠沙箱会被自动唤醒冷启动约 2–3 秒keepAlive: false自动休眠成本最优keepAlive: true永不休眠成本更高且必须显式调用destroy()释放资源api.md 用try/finally保证超时可被环境变量覆盖SANDBOX_INSTANCE_TIMEOUT_MS、SANDBOX_PORT_TIMEOUT_MS日志级别/格式可用SANDBOX_LOG_LEVELdebug|info|warn|error与SANDBOX_LOG_FORMATjson|pretty调整开发建议debugpretty生产建议info/warnjson。进程就绪与冷启动优化对首个请求慢的优化gotchas.mdSlow first request与模式文档的Process Readiness Pattern互补优先复用沙箱用sleepAfter而非不断创建新 ID用 Cron Trigger 预热triggers.crons: [*/5 * * * *]配合scheduled处理器里执行一次sandbox.exec(echo keepalive)唤醒沙箱configuration.mdCron Triggers对关键沙箱设keepAlive: true。错误处理与重试模式文档各示例大多直接返回结果生产实现需要补上 api.md 的错误处理命令失败检查result.success、result.exitCode、result.stderrSDK 错误按error.code分支——FILE_NOT_FOUND、CONTAINER_NOT_READY应重试、TIMEOUT等。gotchas.md 给出了标准重试实现async function execWithRetry(sandbox, cmd) { for (let i 0; i 3; i) { try { return await sandbox.exec(cmd); } catch (e) { if (e.code CONTAINER_NOT_READY) { await new Promise(r setTimeout(r, 2000)); continue; } throw e; } } }长命令记得设置timeout选项如timeout: 30000exec 默认上限 120s防止任务失控。模式选型小结与相关资源八个模式覆盖了 Sandbox 的主流使用场景选型时可参考以下对照模式核心 API典型场景AI 代码执行createCodeContext/runCodeAI Agent 代码解释器、数据分析交互式开发环境startProcess/exposePort云端 IDE、临时开发沙箱WebSocket 实时服务wsConnect/exposePort聊天、协作编辑、实时终端进程就绪startProcess/waitForPort任何后台服务暴露前的就绪保障R2 持久化mountBucket/unmountBucket数据处理、ETL、持久工作区CI/CDexecstream/onOutput构建、测试、安装依赖多租户createSession/getSession用户代码执行平台、作业隔离Git 操作exec secrets拉取仓库、认证克隆、版本化工作流更深入的 API 细节、配置项与陷阱清单可继续阅读同一参考目录下的 sandbox README、api.md、configuration.md 与 gotchas.mdSandbox 所依赖的容器运行时与 Durable Object 基础设施分别见 containers 参考文档 与 durable-objects 参考文档整套 Skill 的定位与产品决策树可参阅 SKILL.md。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进