Dynamic Workers、Containers 与 Sandbox:关系、区别与使用方式

This article is extracted from the chat log with AI. Please identify it with caution.

说明:本文由 Codex 根据作者提供的主题、对话素材与 Cloudflare 官方文档辅助生成,属于 AI 生成/整理内容,非作者原创。请读者自行甄别并交叉验证。

Cloudflare 的 Dynamic Workers、Containers 与 Sandbox SDK 很容易被误认为是三个平级的“沙箱产品”。实际并非如此:

  • Dynamic Workers:由一个已部署的 Worker 在运行时加载并执行另一段 Workers 兼容代码。
  • Containers:运行自定义镜像的完整 Linux 计算平台。
  • Sandbox SDK:建立在 Containers 与 Durable Objects 之上的高层 SDK,面向不可信代码执行、AI Agent 和在线开发环境。

因此,Dynamic Workers 是一条轻量的隔离执行路线;Sandbox SDK 则是基于 Containers 的产品化封装。若仅泛指“sandbox”这个概念,三者都可参与构建隔离执行系统;但 Cloudflare 正式产品名为 Sandbox SDK 的实现并不会自动切换到 Dynamic Workers。

本文按 2026-08-07 的官方文档整理。Dynamic Workers 仍处于快速演进阶段,价格、限额和 API 应以文末官方链接为准。

1. 先看架构关系#

请求
已部署的父 Worker
  ├─ Dynamic Worker
  │    └─ 运行时加载的 Worker isolate
  ├─ Container Durable Object
  │    └─ Container:独立 Linux VM,运行自定义镜像
  └─ Sandbox SDK
       └─ Sandbox Durable Object
            └─ Container:独立 Linux VM,执行不可信代码

Containers 的请求通常经过 Worker 和对应的 Durable Object;Container class 继承 Durable Object,后者负责寻址、生命周期与持久状态,镜像进程则运行在独立 Linux VM 中。Sandbox SDK 进一步将这条链路包装成命令、文件、进程、终端和预览等易用 API。Containers 架构与生命周期 Sandbox SDK 架构

维度Dynamic WorkersContainersSandbox SDK
本质运行时 Worker Loader 原语通用容器计算能力安全代码执行 SDK
执行环境Worker isolate;JavaScript / Python独立 Linux VM;任意可容器化运行时独立 Linux VM;预置 Python、Node.js、Git 等工具
代码提供方式请求期间传入 modules部署时构建并推送 Docker/OCI 镜像部署镜像后,用 SDK 写文件、执行命令或启动进程
主 APIenv.LOADER.load() / get()ContainergetContainer()getSandbox()exec()、文件和进程 API
状态边界不可依赖 isolate 内存DO SQLite 可持久;容器磁盘易失Sandbox ID 稳定;容器休眠后运行态数据易失
典型场景AI 生成小工具、预览、自动化自定义镜像、原生依赖、服务进程AI 编程代理、代码解释器、在线 IDE、CI

2. Dynamic Workers:运行时装载 Worker 代码#

Dynamic Workers 不会产生一个带独立域名和独立部署版本的普通 Worker。开发者先部署父 Worker,再给它配置 Worker Loader binding:

{
  "name": "dynamic-host",
  "main": "src/index.ts",
  "compatibility_date": "2026-08-07",
  "worker_loaders": [
    { "binding": "LOADER" }
  ]
}

父 Worker 在请求中决定动态代码、网络权限、可访问能力和资源限制:

const worker = env.LOADER.get('app:content-hash', async () => ({
  compatibilityDate: '2026-08-07',
  mainModule: 'index.js',
  modules: {
    'index.js': 'export default { fetch() { return new Response("hello"); } };',
  },
  globalOutbound: null,
  limits: { cpuMs: 50, subRequests: 10 },
}));

return worker.getEntrypoint().fetch(request);

load(code) 适合一次性任务,每次都会创建新的 Dynamic Worker;get(id, callback) 会按稳定 ID 尽力复用已加载的代码与 isolate,适合同一版本的应用。但缓存没有持久性保证,甚至同一个 stub 的两次调用也不保证进入同一 isolate。因此,动态代码不能把内存当成可靠状态;代码、依赖或权限变化时必须换 ID。Dynamic Workers 入门 Worker Loader API

Dynamic Workers 支持 JavaScript(ES modules 与 CommonJS)和 Python。TypeScript 与 npm 依赖需要在传入前编译、解析依赖并 bundle;Python 需要 python_workers compatibility flag,且官方提示其启动通常较 JavaScript 慢。

安全模型:默认最小权限,而不是“扔进去就安全”#

隔离的关键是 capability-based security。动态代码只能使用父 Worker 明确传入的 env 数据或 Service Binding。最稳妥的结构是:父 Worker 定义一个很小的 RPC 接口,例如“读取当前租户的某项数据”或“向已批准的服务发送消息”,将鉴权、密钥、审计和配额保留在父 Worker。

尤其需要注意:未设置 globalOutbound 时,动态 Worker 默认继承父 Worker 的网络能力,通常可以访问公网。处理不可信代码时,应默认设置 globalOutbound: null;若确实需要联网,则把所有出站请求转给父 Worker 的网关,在那里做 allowlist、日志与凭据注入。Bindings 与 capability 模型 Egress control

若动态代码需要持久化数据,可使用 Durable Object Facets:由开发者部署的 supervisor Durable Object 管理动态加载的 DO class,每个 facet 拥有与 supervisor 相互隔离的 SQLite 数据库。Durable Object Facets

3. Containers:完整运行时与镜像控制#

Containers 用于需要完整 Linux 能力的工作负载,例如原生二进制、浏览器或编译器、特定语言运行时、大内存计算、长连接服务,或者已有 Docker 镜像的迁移。

{
  "containers": [
    {
      "class_name": "AppContainer",
      "image": "./Dockerfile",
      "instance_type": "basic",
      "max_instances": 10
    }
  ],
  "durable_objects": {
    "bindings": [
      { "name": "APP_CONTAINER", "class_name": "AppContainer" }
    ]
  },
  "migrations": [
    {
      "tag": "v1",
      "new_sqlite_classes": ["AppContainer"]
    }
  ]
}
import { Container, getContainer } from '@cloudflare/containers';

export class AppContainer extends Container {
  defaultPort = 8080;
  sleepAfter = '10m';
}

export default {
  async fetch(request, env) {
    const id = new URL(request.url).pathname.split('/').at(-1) ?? 'default';
    return getContainer(env.APP_CONTAINER, id).fetch(request);
  },
};

稳定 ID 适合把同一用户、文档、房间或任务路由到同一个逻辑实例;可互换的无状态实例则可用 getRandom() 分流。当前 Containers 的扩缩容需要显式管理实例 ID 或固定数量的随机实例池,不应假设它已有传统容器平台的自动横向扩缩容。Containers 入门 扩缩容与路由

Container 冷启动常见约 1–3 秒,但会随镜像大小和入口程序而变化。其磁盘并非持久盘:实例休眠或重启后,文件系统会回到镜像初始状态。小型强一致状态应存入 this.ctx.storage 的 Durable Object SQLite;文件和大对象应放在 R2 等外部存储。镜像须为 linux/amd64,本地部署时由 Docker 构建并通过 Wrangler 推送到 Cloudflare Registry。生命周期、磁盘与镜像 规格与限制

Containers 需要绑定 KV、R2、D1 或其他 Workers 资源时,推荐经 outbound handler 转发。容器只访问一个虚拟 HTTP 主机,Worker 侧 handler 再访问真实 binding;这样可按 Container ID 限制数据范围,也无需把云平台凭据放进镜像。连接 Workers bindings

4. Sandbox SDK:专为不可信代码执行准备#

Sandbox SDK 把“管理 Container + 提供 Linux 代码执行接口”打包为较高层的 TypeScript API。它可运行 shell 命令和 Python/Node 程序、读写文件、管理后台进程、创建交互式终端、维护代码解释器上下文、暴露服务,并挂载或备份对象存储。

官方模板:

npm create cloudflare@latest -- my-sandbox \
  --template=cloudflare/sandbox-sdk/examples/minimal

Worker 中的典型调用如下:

import { getSandbox, type Sandbox } from '@cloudflare/sandbox';

export { Sandbox } from '@cloudflare/sandbox';

const sandbox = getSandbox(env.Sandbox, 'user-123', {
  transport: 'rpc',
  enableDefaultSession: false,
});

await sandbox.writeFile('/workspace/main.py', 'print("hello")');
const result = await sandbox.exec(
  'python3 /workspace/main.py',
  { timeout: 30_000 },
);

真实应用必须在调用 getSandbox() 前完成认证,并将 sandbox ID 绑定到单一用户或租户。不要把用户输入直接拼入 shell 命令;先用文件 API 写入源代码,再以固定命令执行更安全。

这里最重要的状态边界是:Sandbox ID 是稳定的 Durable Object 身份,不是持久化文件系统。 容器活跃期间,文件、进程、shell session 与代码解释器变量都会保留;默认空闲一段时间后容器会停止,下次访问会启动干净环境。跨重启数据应保存到 R2、S3、GCS 或 Durable Object SQLite。Sandbox 生命周期

此外,同一个 sandbox 内的 session 共享文件、进程和 localhost 网络。session 只是工作上下文,不是多租户安全边界;不同不可信主体必须使用不同 sandbox ID。每个 sandbox 运行在独立 VM 中,因此 sandbox 与 sandbox 之间才具有文件、进程、网络与资源隔离。Sandbox 安全模型

Sandbox API 仍在更新。新项目应优先参考官方 2026 迁移指南:优先使用 RPC transport,并使用 Tunnel API 替代较旧的端口暴露方式。

5. 选型与成本#

可以用下面的规则快速选择:

需求首选
不可信代码只需 Workers API,且只应获得少量受控能力Dynamic Workers
需要 shell、文件系统、编译器、原生依赖或自定义镜像Containers
需要执行 AI Agent / 用户代码,并希望直接使用命令、文件、进程、终端、代码解释器能力Sandbox SDK

成本不能只比较“每次调用价格”。Dynamic Workers 按每日唯一 Dynamic Worker、请求与 CPU 时间计费;稳定版本 ID 的 get() 有助于避免重复创建。Containers 则在运行期间按实例的内存、磁盘和活跃 CPU 计费,休眠后停止容器计费,并同时产生 Worker、Durable Object、网络出站与日志等费用。Sandbox SDK 没有独立的底层执行计费,继承 Containers 以及相应 Worker/DO 的用量模型。Dynamic Workers 定价 Containers 定价 Sandbox 定价

最后,无论选哪条路线,隔离都不等于认证授权。父 Worker 都应承担认证、租户映射、配额、审计和网络策略职责。Dynamic Workers 应默认断网后逐项授予 capability;Containers 与 Sandbox SDK 应按租户划分实例,并通过出站控制避免秘密和不受限网络访问进入不可信代码环境。

继续深入#

参考资料#

本文共 3331 字,创建于 Aug 7, 2026

相关标签: Cloud, DevOps, TypeScript, ByAI