迁移稳定版 → Sandbox SDK 1.0 预览版(@next)
执行移植。按顺序执行以下步骤。详细内容参见文档——当某一步需要细节时,请获取链接页面。
新项目应从 @next(sandbox-next)开始,而非此技能。日常稳定版工作 → sandbox-stable。如果需要进行已弃用 API 清理但不迁移到 @next,请首先参考 2026 弃用指南。
现有应用应在条件允许时迁移,以便在 1.0 成为稳定版本时做好准备。在用户同意之前,请勿强制进行生产环境切换。
优先使用已安装的 @next 类型和迁移文档,而非记忆。
工作流程
- 审查硬性规则和替换映射表
- 审计代码库;列出匹配项和目标形态
- 与用户确认(切换、桥接、Python 镜像、不明确的站点)
- 升级包、镜像和代码
- 验证
在需要用户决策的步骤后停止。
硬性规则
- Worker 包和容器镜像必须为相同的
@next版本线。 - 生产切换使用立即容器 rollout。稳定版和
@next的控制协议不兼容(双向);渐进式 rollout 会导致中断的混合窗口。正在进行的容器工作可能会停止。 - 切换后,
await sandbox.exec(...)表示进程已启动,而非命令已完成。 - Argv 按原样传递(无隐式 shell)。Shell 语法需要显式指定 shell 二进制文件。
- 进程句柄没有 stdin → 用于交互式输入的终端。
- 观察的
timeout/AbortSignal仅取消等待,而非进程本身。 - 没有一个适用于所有错误的单一重试循环。
- 不要发明 API(例如,
gitCheckout在核心上、进程 stdin、字符串执行完成辅助工具)。 - 自部署桥接保持在稳定版(尚未属于预览版的一部分)。
替换映射表
| 稳定版 | @next |
|---|---|
SANDBOX_TRANSPORT / transport / setTransport | 移除——仅 RPC |
await sandbox.exec("cmd") → 缓冲结果 | await sandbox.exec(argv) → 句柄,然后 output / 等待 |
execStream / startProcess | 相同句柄:logs、waitFor*、kill |
| 默认/命名会话 | 已移除——每个启动使用 cwd/env,或一个 shell 脚本 |
sandbox.terminal(request) / 会话终端 | createTerminal + terminal.connect(request) |
xterm sessionId | terminalId |
Sandbox 上的解释器方法 | withInterpreter → sandbox.interpreter.* |
gitCheckout | 通过 exec 使用 argv git |
| 字符串类型的 kill 信号 | 仅数字类型 |
文件、挂载点、备份、端口、隧道、proxyToSandbox | 基本不变(在稳定版页面上忽略会话/传输相关部分) |
详细内容:迁移 · 移植后,日常使用 → sandbox-next
审计
rg 'SANDBOX_TRANSPORT|transport:|setTransport|enableDefaultSession|createSession|getSession|deleteSession|execStream\(|startProcess\(|killProcess\(|sandbox\.terminal\(|sessionId|gitCheckout\(|SandboxTransport|ExecutionSession'
另外检查:字符串 exec(、cd 后跟后续 exec、在 Sandbox 上直接使用 createCodeContext / runCode。
确认(需要时询问)
- 是否允许使用
--containers-rollout=immediate进行生产切换(正在运行的进程/终端/流可能会停止)? - 是否使用了自部署桥接?保持其处于稳定版。
- Python 解释器 → 是否使用
-python镜像变体? - 是否存在映射表未覆盖的调用点?
升级
包和镜像
npm install @cloudflare/sandbox@next
FROM cloudflare/sandbox:next
# Python: cloudflare/sandbox:next-python
当不是使用浮动的 next 标签时,Worker 和镜像上的预发布标签必须相同。
按区域代码
应用映射表中的替换。对于每个区域,从文档中实现——而不是依据稳定版的习惯:
| 区域 | 文档 |
|---|---|
| 命令 / 句柄 / 等待 | 进程 · 进程 API |
cwd / env / 机密 | 环境 · 出站流量 |
| 移除会话 | 迁移 · 生命周期 |
| 终端 | 终端 |
| 解释器 | 解释器 |
| 错误 | 错误 |
| 跨请求的持久性任务 | 进程执行 — 生命周期 / 持久性 |
命令(形态):
// 之前(稳定版)
const result = await sandbox.exec("npm test");
// 之后(@next)
const process = await sandbox.exec(["/bin/bash", "-lc", "npm test"]);
const result = await process.output({ encoding: "utf8" });
const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
cwd: "/workspace/app",
});
await server.waitForPort(3000, { timeout: 60_000 });
await server.kill(); // 数字;默认 15
终端(形态):
const terminal = await sandbox.createTerminal({ command: ["bash"], cwd: "/workspace" });
const t = await sandbox.getTerminal(terminal.id);
if (!t) return new Response("terminal gone", { status: 410 });
return t.connect(request, { cursor, cols, rows });
解释器(形态):
import { Sandbox as BaseSandbox } from "@cloudflare/sandbox";
import { withInterpreter } from "@cloudflare/sandbox/interpreter";
export class Sandbox extends BaseSandbox<Env> {
interpreter = withInterpreter(this);
}
Git(形态):
const clone = await sandbox.exec(
["git", "clone", "--depth", "1", "--", repoUrl, "/workspace/repo"],
{ cwd: "/workspace" },
);
const result = await clone.output({ encoding: "utf8" });
完全删除传输设置。移除会话 API。使用独立的 sandbox ID 隔离用户。
部署切换
先进行暂存/分支部署。生产环境是一次匹配的 Worker + 镜像的部署:
npx wrangler deploy --containers-rollout=immediate
将 rollout_active_grace_period 保持默认值 0(如果已调高,则设置为 0)。切换后,部署前的进程/终端 ID 将失效。详细内容:迁移 · 容器 rollout
验证
- Lockfile 和 Dockerfile 使用相同的
@next版本线 - 针对
@next进行类型检查 - 冒烟测试 argv
exec+output({ encoding: "utf8" }) - 冗长进程 / 终端 / 解释器(如果使用)进行冒烟测试
- 区分错误:不可用 / 中断的 RPC / 过期 / 本地等待
- Sandbox 环境中没有实时机密
- 再次 grep 移除的 API
- 生产环境使用了
--containers-rollout=immediate
然后,日常工作使用 sandbox-next。
红旗——停止并修复
- 将
@nextWorker 与稳定版镜像混合使用(或相反) - 为此切换进行渐进式容器 rollout
- 将
await exec视为命令完成 - 假设
cd/ 导出在多个exec调用之间持久存在 - 为每个错误使用一个重试封装
- 发明
gitCheckout、进程 stdin 或未文档化的 API - 部署后保留切换前的进程/终端 ID
- 未获用户同意强制生产切换
- 在
setEnvVars/ 启动env中放入实时机密