跳转到内容
搜索文档

Sandbox Bridge

最后更新 查看 MarkdownAgent 设置

Sandbox Bridge 是一个参考实现的 Cloudflare Worker,它将 Sandbox SDK 作为 HTTP API 公开。任何 HTTP 客户端 — Python 脚本、Node.js 服务、CI 流水线 — 都可以创建并控制 sandbox,而无需编写 Worker。

为什么使用 Bridge

Sandbox SDK 专为在 Cloudflare Workers 内部使用而设计。如果你的应用程序运行在 Workers 生态系统之外,它将无法直接与 sandbox 进行交互。

Bridge 将 Sandbox SDK 作为标准的 HTTP API 公开,因此你可以从任何语言或平台创建和控制 sandbox。

主要 Sandbox SDK 方法 映射到单独的 HTTP 端点。Bridge 添加了身份验证、输入验证、工作区路径限定,以及用于即时容器启动的可选 热池 (warm pool)

部署

将 Bridge Worker 部署到你的 Cloudflare 账户:

Deploy to Cloudflare

该按钮部署 Worker 并生成用于身份验证的 SANDBOX_API_KEY secret。当部署完成时,请记录你的 Worker URL 和 API 密钥 — 本页上的每个示例都使用它们。

手动部署

如果你希望一步步部署,请构建项目脚手架并手动部署。

先决条件:

步骤:

  1. 构建 Bridge 项目脚手架:

    npm create cloudflare -- sandbox-bridge --template=cloudflare/sandbox-sdk/bridge/worker
    cd sandbox-bridge
  2. 进行 Cloudflare 身份认证:

    npx wrangler login
  3. 设置 API 密钥 secret。选择任意强 Token 值 — 客户端必须将此作为 Bearer token 发送:

    openssl rand -hex 32 | tee /dev/stderr | npx wrangler secret put SANDBOX_API_KEY

    该密钥会打印到终端并管道传输给 Wrangler。请保存它 — 你需要它来对 API 请求进行身份验证。

  4. 部署 Worker:

    npx wrangler deploy
  5. 验证部署:

    curl https://cloudflare-sandbox-bridge.<your-subdomain>.workers.dev/health

    你应该能看到 {"ok":true}

容器镜像 (Container image)

Bridge 的 Dockerfile 扩展了 cloudflare/sandbox 基础镜像,并预安装了常用的 Agent 工具:

  • 语言: Python 3.13, Node.js, Bun
  • 工具: git, ripgrep, curl, wget, jq, tar, sed, gawk, procps

你可以自定义 Dockerfile 以添加你的工作负载所需的语言、系统包或工具。

用法

所有示例均假设设置了以下环境变量:

export SANDBOX_API_URL=https://cloudflare-sandbox-bridge.<your-subdomain>.workers.dev
export SANDBOX_API_KEY=<your-token>

创建 Sandbox 并运行命令

# 创建 sandbox
SANDBOX_ID=$(curl -s -X POST "$SANDBOX_API_URL/v1/sandbox" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" | jq -r '.id')

echo "Sandbox ID: $SANDBOX_ID"

# 运行命令
curl -s -X POST "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/exec" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"argv": ["sh", "-lc", "echo hello from the sandbox"], "timeout_ms": 10000}'

# 完成后销毁 sandbox
curl -s -X DELETE "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID" \
  -H "Authorization: Bearer $SANDBOX_API_KEY"
const API_URL = process.env.SANDBOX_API_URL;
const API_KEY = process.env.SANDBOX_API_KEY;

const headers = {
  Authorization: `Bearer ${API_KEY}`,
  "Content-Type": "application/json",
};

// 创建 sandbox
const { id } = await fetch(`${API_URL}/v1/sandbox`, {
  method: "POST",
  headers,
}).then((r) => r.json());

console.log(`Sandbox ID: ${id}`);

// 运行命令
// 响应为带有以下 SSE 事件的 text/event-stream:
//   event: stdout  — data 为 Base64 编码的输出块
//   event: stderr  — data 为 Base64 编码的错误块
//   event: exit    — data 为 JSON: {"exit_code": 0}
//   event: error   — data 为 JSON: {"error": "...", "code": "..."}
const execRes = await fetch(`${API_URL}/v1/sandbox/${id}/exec`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    argv: ["sh", "-lc", "echo hello from the sandbox"],
    timeout_ms: 10000,
  }),
});

console.log(await execRes.text());

// 完成后销毁 sandbox
await fetch(`${API_URL}/v1/sandbox/${id}`, {
  method: "DELETE",
  headers,
});
# /// script
# dependencies = ["httpx"]
# ///
import os
import httpx

API_URL = os.environ["SANDBOX_API_URL"]
API_KEY = os.environ["SANDBOX_API_KEY"]

headers = {"Authorization": f"Bearer {API_KEY}"}

# 创建 sandbox
resp = httpx.post(f"{API_URL}/v1/sandbox", headers=headers)
sandbox_id = resp.json()["id"]
print(f"Sandbox ID: {sandbox_id}")

# 运行命令
# 响应为带有以下 SSE 事件的 text/event-stream:
#   event: stdout  — data 为 Base64 编码的输出块
#   event: stderr  — data 为 Base64 编码的错误块
#   event: exit    — data 为 JSON: {"exit_code": 0}
#   event: error   — data 为 JSON: {"error": "...", "code": "..."}
exec_resp = httpx.post(
    f"{API_URL}/v1/sandbox/{sandbox_id}/exec",
    headers=headers,
    json={
        "argv": ["sh", "-lc", "echo hello from the sandbox"],
        "timeout_ms": 10000,
    },
)
print(exec_resp.text)

# 完成后销毁 sandbox
httpx.delete(f"{API_URL}/v1/sandbox/{sandbox_id}", headers=headers)

写入和读取文件

# 写入文件
curl -s -X PUT "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/file/workspace/hello.py" \
  -H "Authorization: Bearer $SANDBOX_API_KEY" \
  --data-binary 'print("hello world")'

# 读取文件
curl -s "$SANDBOX_API_URL/v1/sandbox/$SANDBOX_ID/file/workspace/hello.py" \
  -H "Authorization: Bearer $SANDBOX_API_KEY"
// 写入文件
await fetch(`${API_URL}/v1/sandbox/${id}/file/workspace/hello.py`, {
  method: "PUT",
  headers,
  body: 'print("hello world")',
});

// 读取文件
const content = await fetch(
  `${API_URL}/v1/sandbox/${id}/file/workspace/hello.py`,
  { headers },
).then((r) => r.text());

console.log(content);
# /// script
# dependencies = ["httpx"]
# ///
import os
import httpx

API_URL = os.environ["SANDBOX_API_URL"]
API_KEY = os.environ["SANDBOX_API_KEY"]
SANDBOX_ID = os.environ["SANDBOX_ID"]  # 来自 "创建 sandbox" 步骤
headers = {"Authorization": f"Bearer {API_KEY}"}

# 写入文件
httpx.put(
    f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py",
    headers=headers,
    content=b'print("hello world")',
)

# 读取文件
content = httpx.get(
    f"{API_URL}/v1/sandbox/{SANDBOX_ID}/file/workspace/hello.py",
    headers=headers,
).text
print(content)

保持 Bridge 更新

Bridge 的大部分逻辑都在 @cloudflare/sandbox 包中。要引入最新的改进:

  1. 更新 SDK 依赖项:

    npm update @cloudflare/sandbox
  2. 重新部署:

    npx wrangler deploy

查看 sandbox-sdk releases 以了解可能需要手动更新的 Dockerfile 或 Bridge 配置更改。

源代码与示例

Bridge 的源代码和示例可以在 GitHub 上找到:

相关资源

这篇文档对您有帮助吗?