尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

如何快速构建隔离代码执行环境:Cloudflare Sandbox SDK 完整实战指南

发布时间:2026/9/14 5:55:10

资讯中心
01
ARTICLE

如何快速构建隔离代码执行环境:Cloudflare Sandbox SDK 完整实战指南

如何快速构建隔离代码执行环境:Cloudflare Sandbox SDK 完整实战指南
如何快速构建隔离代码执行环境Cloudflare Sandbox SDK 完整实战指南【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skillsCloudflare Sandbox SDK 让你在 Cloudflare 边缘的隔离容器里安全运行不受信任的代码。读完本文你会从零跑通一个沙箱 Worker掌握命令执行、文件管理、后台进程、端口暴露、多租户会话与 AI 代码解释器并拿到一套可直接上生产的成本与安全清单。快速上手5 分钟跑通第一个隔离沙箱先把 Sandbox 理解成一台带遥控器的临时虚拟机每个沙箱由一个 Durable Object 加一个容器组成相同 ID 永远复用同一个沙箱文件系统、进程、网络彼此完全隔离。它典型用在 AI 代码执行、交互式开发环境、数据分析和多租户执行场景。最小可运行示例是一个 Worker 入口文件import { 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 { // CRITICAL: 预览 URL 生效的前提必须最先调用 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 }); } };配套需要两个配置文件。wrangler.jsonc声明容器与绑定{ name: my-sandbox-worker, main: src/index.ts, compatibility_date: 2025-01-01, // 新项目请使用当前日期 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] }] }配置项作用class_name容器的 DO 类名必须与durable_objects.bindings中的类名一致image指向你的 Dockerfile决定沙箱里预装了什么instance_type实例规格lite 256MB/0.5vCPU默认、standard 512MB/1vCPU、heavy 1GB/2vCPUmax_instances并发容器上限高流量场景可调大Dockerfile定义沙箱环境FROM docker.io/cloudflare/sandbox:latest RUN pip3 install --no-cache-dir pandas numpy matplotlib EXPOSE 8080 3000 # wrangler dev 本地调试必需⚠️EXPOSE只是本地调试需要——生产环境会自动暴露所有端口但漏写它本地就会报端口找不到。配置完成后wrangler dev本地调试、wrangler deploy部署生产、wrangler tail看日志、wrangler containers list检查容器状态。完整配置说明见 configuration.md。核心场景把沙箱用进真实业务如何运行命令并拿到标准输出exec是沙箱最核心的入口一次调用返回五元组结果const result await sandbox.exec(python3 script.py, { cwd: /workspace/project, // 指定工作目录 env: { API_KEY: secret }, // 注入进程级环境变量 timeout: 30000 // 30 秒超时默认 120 秒 }); if (!result.success) console.error(result.exitCode, result.stderr);返回字段含义stdout/stderr标准输出 / 标准错误exitCode退出码0 表示成功success是否成功等价于退出码为 0需要显式检查duration本次执行耗时一个容易忽略的细节exec不会因命令失败抛异常失败只是success: false。如果你只catch不检查success错误的命令会被静默吞掉。长耗时命令如npm install可以开stream: true配合onOutput: (stream, data) ...回调实时打印进度。如何管理容器内的持久化文件const { content } await sandbox.readFile(/workspace/data.txt); await sandbox.writeFile(/workspace/sub/dir/file.txt, content); // 自动创建父目录 const files await sandbox.listFiles(/workspace); await sandbox.deleteFile(/workspace/dir, { recursive: true }); // 递归删除目录 await sandbox.pathExists(/workspace/file.txt); // 存在性检查方法用途readFile读取返回{ content }writeFile写入自动补全不存在的中间目录省掉mkdir -plistFiles/deleteFile列目录 / 删文件支持recursive: truemkdir/pathExists建目录 / 查存在⚠️ 持久化有硬性约定/tmp等临时路径的文件在容器休眠唤醒后会丢失持久数据一律放/workspace见 gotchas.md 的 File not persisting。如何启动后台进程并等待就绪startProcess用于 HTTP 服务这类长期进程与一次性的exec相对const process await sandbox.startProcess(node server.js, { processId: server, // 自定义标识后续管理靠它 cwd: /workspace/public, env: { PORT: 8080 } }); // 返回 { id, pid, command }pid 是容器内系统 PID await process.waitForPort(8080); // 等端口开始监听 await process.waitForLog(/Server running/); // 或等日志匹配正则 await process.waitForExit(); // 或等进程退出三种等待方式分别对应端口就绪、日志模式匹配、进程退出。关键细节是先waitForPort再对外暴露否则用户可能拿到一个还连不上服务的 URL。进程管理一组接口listProcesses()列全部、getProcess(server)查单个、stopProcess(server)停止、getProcessLogs(server)取日志。如何暴露容器端口拿到对外访问地址容器内端口默认不可达exposePort会生成一个带自动令牌的预览 URLconst { url } await sandbox.exposePort(8080, { hostname: request.hostname // 用当前请求主机名生成 }); // → https://8080-sandbox-abc123.yourdomain.com预览 URL 形态里藏着自动生成的令牌每次暴露令牌都会变天然防止未授权访问。配套的isPortExposed(8080)、getExposedPorts(hostname)、unexposePort(8080)用来查询和回收。⚠️ 预览 URL 有四个硬性前提缺一不工作自定义域名 通配符 DNS*.yourdomain.com → worker.yourdomain.com不支持.workers.devgetSandbox传normalizeId: trueID 小写化fetch 里最先调用proxyToSandbox()域名解析正确生效。进阶玩法多租户、AI 解释器与实时通信如何构建 AI 代码解释器变量跨轮次保留调用链路Agent 提交代码 → getSandbox → createCodeContext(带变量) → runCode → 富输出返回。const ctx await sandbox.createCodeContext({ language: python, variables: { data: [1, 2, 3, 4, 5] } }); const result await ctx.runCode( import matplotlib.pyplot as plt plt.plot(data, [x**2 for x in data]) plt.savefig(plot.png) print(fProcessed {len(data)} points) ); // 返回 { outputs: [{ type: text|image|html, content }], error } await ctx.runCode(print(data[0])); // 无需重新声明data 仍在outputs是富输出数组每个元素带typetext/image/html与contenterror非空即代码异常——这对对接 Agent 很友好图片可以直接回传给前端。⚠️ 代码上下文状态是易失的容器休眠唤醒后变量全部清空必须在唤醒后重建上下文。如何做多租户隔离执行调用链路请求头 X-User-ID → getSandbox → 会话不存在则 createSession → session.exec。const userId request.headers.get(X-User-ID); const sandbox getSandbox(env.Sandbox, multi-tenant); let session; try { session await sandbox.getSession(userId); } catch { session await sandbox.createSession({ // 首次访问才创建 id: userId, cwd: /workspace/users/${userId}, env: { USER_ID: userId } }); } const result await session.exec(python3 -c print(1));每个会话维护独立的 shell 状态、环境变量、cwd 和进程命名空间session上暴露与沙箱相同的 APIexec、文件操作等。deleteSession(user-123)可清理会话。安全要点沙箱之间文件系统、网络、进程完全隔离且不能直接通信多租户应用应给每个租户唯一 sandbox ID。如何代理 WebSocket 实时连接调用链路WS 握手请求 → 识别 Upgrade 头 → getSandbox → wsConnect 代理到容器端口。export 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); return await sandbox.wsConnect(request, 8080); // 代理到容器 8080 } return new Response(Not a WebSocket request, { status: 400 }); } };想让客户端自己拿连接地址可对非 WS 请求exposePort(8080, { hostname })后把https替换成wss返回。容器侧需要装 WS 依赖如 Dockerfile 里RUN npm install -g ws。更多工作流CI/CD、R2 桶挂载数据处理等见 patterns.md。生产级实践成本、安全与资源释放清单条目为什么怎么做显式销毁沙箱keepAlive: true的容器永不休眠不销毁就持续计费放进finallytry { ... } finally { await sandbox.destroy(); }destroy()会清掉文件、进程、会话、已暴露端口复用沙箱 ID每次新建 ID 都触发容器构建慢且贵按业务维度固定 ID如user-${userId}禁止Date.now()拼 ID控制休眠策略冷启动有 2-3 秒频繁休眠影响体验默认sleepAfter: 10m自动休眠省钱关键沙箱用 Cron 触发器每 5 分钟exec(echo keepalive)预热密钥管理硬编码密钥进代码库是安全事故wrangler secret put GITHUB_TOKEN存入运行时exec(cmd, { env: { GIT_TOKEN: env.GITHUB_TOKEN } })注入防命令注入exec接收 shell 字符串拼用户输入可被注入✅ 先writeFile把用户代码写到文件再exec(python3 /workspace/user_code.py)超时兜底长任务拖死请求链路exec默认 120 秒长命令显式传timeout容器供给/端口就绪默认 30s/90s可用SANDBOX_INSTANCE_TIMEOUT_MS、SANDBOX_PORT_TIMEOUT_MS覆盖避坑与排错高频错误速查表错误码 / 现象原因解法CONTAINER_NOT_READY容器仍在供给首次请求或休眠唤醒等 2-3 秒后重试最多 3 次封装成execWithRetryFILE_NOT_FOUND读取了不存在的文件先pathExists检查或先写入TIMEOUT操作超时调大timeout或拆任务容器无限运行持续计费keepAlive: true但没调destroy()用完必须destroy()放finally首请求很慢冷启动容器构建 2-3 分钟 / 唤醒 2-3 秒sleepAfter复用 Cron 预热 关键沙箱keepAlive文件丢失写在了/tmp等临时路径持久文件只放/workspace预览 URL 打不开缺自定义域名 / 通配 DNS /normalizeId/proxyToSandbox按上一节四条前提逐项核对normalizeId前后 ID 对不上hash(MyApp)与hash(myapp)是两个不同沙箱全项目保持同一normalizeId取值端口连接被拒Dockerfile 漏写EXPOSE本地调试补EXPOSE port生产自动暴露桶挂载本地失败Bucket 挂载依赖 FUSEwrangler dev无此能力本地用 mock 数据生产验证官方重试模式可直接抄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; } } }完整 API 细节在 api.md坑位清单在 gotchas.md。收尾四条铁律proxyToSandbox()必须最先调用否则预览 URL 全部失效相同 ID 复用沙箱持久文件只放/workspacekeepAlive: true必须配对finally里的destroy()CONTAINER_NOT_READY要重试命令失败要查success字段。把 gotchas.md 当生产前最后一遍 checklist你的沙箱就能安全、低成本地跑起来。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。