用于 JavaScript/ TypeScript 的 Alibaba 沙盒 SDK
用于与OpenSandbox进行低等交互的TypeScript/JavaScript SDK. 它提供了创建,管理和互动安全沙盒环境的能力,包括执行 shell 命令,管理文件,并读取资源度量.
安装
无
npm install @alibaba-group/opensandbox
小时
pnpm add @alibaba-group/opensandbox
线条
yarn add @alibaba-group/opensandbox
快速启动
以下示例显示如何创建沙盒并执行 shell 命令.
说明: 在运行此示例之前, 确保 OpenSandbox 服务正在运行 。 见根 读取 用于启动指令.
import { ConnectionConfig, Sandbox, SandboxException } from "@alibaba-group/opensandbox";
const config = new ConnectionConfig({
domain: "api.opensandbox.io",
apiKey: "your-api-key",
// protocol: "https",
// requestTimeoutSeconds: 60,
});
try {
const sandbox = await Sandbox.create({
connectionConfig: config,
image: "ubuntu",
timeoutSeconds: 10 * 60,
});
const execution = await sandbox.commands.run("echo 'Hello Sandbox!'");
console.log(execution.logs.stdout[0]?.text);
// Optional but recommended: terminate the remote instance when you are done.
await sandbox.kill();
await sandbox.close();
} catch (err) {
if (err instanceof SandboxException) {
console.error(
`Sandbox Error: [${err.error.code}] ${err.error.message ?? ""}`,
);
console.error(`Request ID: ${err.requestId ?? "N/A"}`);
} else {
console.error(err);
}
}
客户端沙盒池
SandboxPool 保持一个最好的缓冲 干净,准备的沙盒。 获得的沙盒成为呼叫器的自有并永不回池;工作完成后杀死它. 池子补充了背景中闲置的缓冲.
import {
AcquirePolicy,
InMemoryPoolStateStore,
SandboxPool,
} from "@alibaba-group/opensandbox";
const pool = SandboxPool.create({
poolName: "workers",
maxIdle: 2,
stateStore: new InMemoryPoolStateStore(),
connectionConfig: { apiKey: process.env.OPEN_SANDBOX_API_KEY },
creationSpec: { image: "ubuntu:24.04" },
});
await pool.start();
const sandbox = await pool.acquire({
sandboxTimeoutSeconds: 3600,
policy: AcquirePolicy.DIRECT_CREATE,
});
try {
await sandbox.commands.run("echo ready");
} finally {
await sandbox.kill();
await sandbox.close();
await pool.shutdown();
}
InMemoryPoolStateStore 是进程本地化的。 对于分布式池,仅在需要的应用程序中安装 Redis 客户端并导入可选的池子子路径 :
npm install redis
import { createClient } from "redis";
import { RedisPoolStateStore } from "@alibaba-group/opensandbox/pool-redis";
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();
const stateStore = new RedisPoolStateStore({ client: redis });
SDK 不导入 redis 从它的主切入点开始,不创建、连接或关闭被注入的客户端。 任何执行的相容客户端 sendCommand(string[]) 可以使用.
泳池热身被录取 warmupCreateQps 每1秒调和勾选。 创造是同步的; warmupConcurrency 限制创建后的准备、准备、更新和承诺阶段。 使用 warmupSandboxPreparer, (中文(简体) ), warmupPostPrepareHealthCheck,以及相应的出场/评出预选的预热能。 设定 connectionConfig.enableTracing 以释放 Open-Teleometry pool.warmup 每个阶段有一个孩子.
SandboxPoolManager.destroy(poolName) 写入共享 DESTROYING 栅栏、排水沟和最佳方法杀死了可见的闲置沙箱、清除了恒水池状态 DESTROYED 墓志铭. drainTimeoutSeconds 在每次排水尝试和限制飞行中沙盒删除前选中; 设置为 0 以禁用该绑定。 国营商店的电话仍须服从商店客户端自己要求的超时. 如果排水口或持续状态清理无法完成,则命名空间仍为 DESTROYING重试 destroy() 同一个池名来完成清理.
用法实例
1. 生命周期管理
管理沙盒生命周期,包括更新、挖掘和恢复.
const info = await sandbox.getInfo();
console.log("State:", info.status.state);
console.log("Created:", info.createdAt);
console.log("Expires:", info.expiresAt); // null when manual cleanup mode is used
await sandbox.pause();
// Resume returns a fresh, connected Sandbox instance.
const resumed = await sandbox.resume();
// Renew: expiresAt = now + timeoutSeconds
await resumed.renew(30 * 60);
通过路过创建一个非过期的沙盒 timeoutSeconds: null数字 :
const manual = await Sandbox.create({
connectionConfig: config,
image: "ubuntu",
timeoutSeconds: null,
});
2. 定制健康检查
定义自定义逻辑以确定沙盒是否准备/健康 。 这可以取代在准备状态检查中使用的默认ping检查 .
const sandbox = await Sandbox.create({
connectionConfig: config,
image: "nginx:latest",
healthCheck: async (sbx) => {
// Example: consider the sandbox healthy when port 80 endpoint becomes available
const ep = await sbx.getEndpoint(80);
return !!ep.endpoint;
},
});
3. 命令执行和流化
实时执行命令并处理输出流.
import type { ExecutionHandlers } from "@alibaba-group/opensandbox";
const handlers: ExecutionHandlers = {
onStdout: (m) => console.log("STDOUT:", m.text),
onStderr: (m) => console.error("STDERR:", m.text),
onExecutionComplete: (c) =>
console.log("Finished in", c.executionTimeMs, "ms"),
};
await sandbox.commands.run(
'for i in 1 2 3; do echo "Count $i"; sleep 0.2; done',
undefined,
handlers,
);
4. 综合文件业务
管理文件和目录,包括读取、写入、列表/搜索和删除.
await sandbox.files.createDirectories([{ path: "/tmp/demo", mode: 755 }]);
await sandbox.files.writeFiles([
{ path: "/tmp/demo/hello.txt", data: "Hello World", mode: 644 },
]);
const content = await sandbox.files.readFile("/tmp/demo/hello.txt");
console.log("Content:", content);
const files = await sandbox.files.search({
path: "/tmp/demo",
pattern: "*.txt",
});
console.log(files.map((f) => f.path));
await sandbox.files.deleteDirectories(["/tmp/demo"]);
5. 终点
getEndpoint() 返回结束点 没有计划 (例如 "localhost:44772") (中文(简体) ). 使用 getEndpointUrl() 如果您想要一个随时可用的绝对 URL( 例如) "http://localhost:44772") (中文(简体) ).
const { endpoint } = await sandbox.getEndpoint(44772);
const url = await sandbox.getEndpointUrl(44772);
6. 快照(经理)
SandboxManager 管理沙盒快照——捕捉出沙盒的状态,通过它恢复出新的沙盒 snapshotId数字 :
import { SandboxManager } from "@alibaba-group/opensandbox";
const manager = SandboxManager.create({ connectionConfig: config });
// Create a snapshot from a running sandbox, then wait until it is Ready
const snapshot = await manager.createSnapshot(sandboxId, {
name: "pre-migration",
});
let info = await manager.getSnapshot(snapshot.id);
while (info.status.state === "Creating") {
await new Promise((r) => setTimeout(r, 2000));
info = await manager.getSnapshot(snapshot.id);
}
// List all snapshots
const page = await manager.listSnapshots();
// Restore: create a new sandbox FROM a snapshot (exactly one of
// image / snapshotId must be provided)
const restored = await Sandbox.create({
connectionConfig: config,
snapshotId: snapshot.id,
});
// Only delete the snapshot after the restore has succeeded
await manager.deleteSnapshot(snapshot.id);
7. 孤立会议
孤立的会话在一个硬化、资源约束的环境中运行多步骤代码,有绑定的挂载——可以通过 sandbox.isolation数字 :
const session = await sandbox.isolation.create({
workspace: { path: "/workspace", mode: "rw" },
profile: "strict",
// Optional bind mounts (source on host, dest inside the session)
binds: [{ source: "/data", dest: "/data", readonly: true }],
});
const run = await session.run("python -c 'print(1+1)'", {
// timeout_seconds: 30, // seconds; applies to run() only —
// runBackground() deliberately ignores it (background runs are not time-limited)
});
console.log(run.logs.stdout[0]?.text);
// Background runs: start, poll until finished, then fetch logs.
// NOTE: field names are snake_case (run_id) — they mirror the raw API
// response and are NOT converted to camelCase.
const bg = await session.runBackground("make build");
let status = await session.getRunStatus(bg.run_id);
while (status.running) {
await new Promise((r) => setTimeout(r, 2000));
status = await session.getRunStatus(bg.run_id);
}
const logs = await session.getRunLogs(bg.run_id);
await session.delete();
8. 积分山
volumes 支持 host, (中文(简体) ), pvc,以及 ossfs 后门. 每卷必须精确指定一个后端.
const sandbox = await Sandbox.create({
connectionConfig: config,
image: "ubuntu",
volumes: [
{
name: "oss-data",
ossfs: {
bucket: "bucket-a",
endpoint: "oss-cn-hangzhou.aliyuncs.com",
accessKeyId: process.env.OSS_ACCESS_KEY_ID!,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET!,
version: "2.0",
},
mountPath: "/mnt/oss",
subPath: "prefix",
},
],
});
9. 沙盒管理(阿明)
使用 SandboxManager 用于行政任务和寻找已存在的沙盒.
import { SandboxManager } from "@alibaba-group/opensandbox";
const manager = SandboxManager.create({ connectionConfig: config });
const list = await manager.listSandboxInfos({
states: ["Running"],
pageSize: 10,
});
console.log(list.items.map((s) => s.id));
await manager.close();
配置
1. 连接配置
这个 ConnectionConfig 类管理 API 服务器连接设置.
运行时注释 :
- 在浏览器中, SDK 使用全局
fetch执行. requestTimeoutSeconds限制等待响应:一旦响应头到达就停止应用(流化响应不被切断). 它从不封盖健康文件上传机体,这可以合法地超过超时;在Node.js上传一个被停滞的上传机体,或者一个在被发送后在超时内没有获得响应头的上传机体被中止而不是被挂起(Go SDK's)ResponseHeaderTimeout(合同).- 在节点.js,每个
Sandbox财务报告和审定财务报表SandboxManager自己通过withTransportIfMissing()除非你通过一个已经启动的ConnectionConfig;共享配置被再用,而SDK只关闭它自己分配的运输. 打电话sandbox.close()或者说manager.close()当你完成后,SDK就可以释放它拥有的代理.
| 参数 | 说明 | 默认 | 环境变量 |
|---|---|---|---|
apiKey | 认证的 API 密钥 | 可选 | OPEN_SANDBOX_API_KEY |
domain | Sandbox 服务域名 (host[:port]),或包括路径前缀(如. https://gw.example.com/opensandbox(中文(简体) ) | localhost:8080 | OPEN_SANDBOX_DOMAIN |
protocol | HTTP 协议 (http编号 :https(中文(简体) ) | http | - 说吧 |
requestTimeoutSeconds | 应用到 SDK HTTP 呼叫中的请求超时 | 30 | - 说吧 |
debug | 启用基本的 HTTP 调试记录 | false | - 说吧 |
headers | 每个请求都应用了额外的信头 | {} | - 说吧 |
useServerProxy | 使用沙盒服务器作为执行/端点请求的代理服务器(例如当客户端无法直接到达沙盒时) | false | - 说吧 |
endpointCacheTtlMs | 缓存的沙盒端点保持有效多久 | 600000 | - 说吧 |
endpointCacheSize | 最大缓存终点数 | 1024 | - 说吧 |
endpointCacheDisabled | 完全禁用端点缓存 | false | - 说吧 |
disableMetrics | 退出创建时的遥测 | false | OPENSANDBOX_DISABLE_METRICS=1 |
enableTracing | Emit 池跟踪上下文标题 | false | - 说吧 |
import { ConnectionConfig } from "@alibaba-group/opensandbox";
// 1. Basic configuration
const config = new ConnectionConfig({
domain: "api.opensandbox.io",
apiKey: "your-key",
requestTimeoutSeconds: 60,
});
// 2. Advanced: custom headers
const config2 = new ConnectionConfig({
domain: "api.opensandbox.io",
apiKey: "your-key",
headers: { "X-Custom-Header": "value" },
});
2. 沙盒创建配置
Sandbox.create() 允许配置沙盒环境.
| 参数 | 说明 | 默认 |
|---|---|---|
image | 要使用的嵌入器图像 | 需求 |
timeoutSeconds | 自动终止超时( 服务器侧 TTL ) | 10分钟 |
entrypoint | 集装箱入境点指挥 | ["tail","-f","/dev/null"] |
resource | CPU 和内存限制( 字符串映射) | {"cpu":"1","memory":"2Gi"} |
env | 环境变量 | {} |
metadata | 自定义元数据标记 | {} |
networkPolicy | 可选外出网络政策(外出) | - 说吧 |
credentialProxy | 可选的 Creditic Vault 代理启动设置 | - 说吧 |
extensions | 服务器定义的额外字段 | {} |
skipHealthCheck | 跳过准备状态检查( E)Running + 健康检查) | false |
healthCheck | 自定义准备状态检查 | - 说吧 |
readyTimeoutSeconds | 最大时间等待准备 | 30 秒钟 |
healthCheckPollingInterval | 等待时的投票间隔( 毫秒) | 200 毫秒( u) |
signal | 中止创建和准备请求 | - 说吧 |
注释:元数据密钥 opensandbox.io/ 用于系统管理的标签,并将被服务器拒绝.
const sandbox = await Sandbox.create({
connectionConfig: config,
image: "python:3.11",
networkPolicy: {
defaultAction: "deny",
egress: [{ action: "allow", target: "pypi.org" }],
},
});
3. 最新运行时间Egress政策
跑道时间 Egress读取并补丁直接通向沙盒 Egress侧车. SDK首先解决了端口的沙盒端点 18080,然后叫侧车 /policy API (英语).
补丁使用合并语义 :
- 新的规则优先于同样的现有规则
target。 。 。 . - 其他目标的现行规则保持不变.
- 在单一的补丁有效载荷内
target赢了. - 当前
defaultAction被保存下来.
const policy = await sandbox.getEgressPolicy();
await sandbox.patchEgressRules([
{ action: "allow", target: "www.github.com" },
{ action: "deny", target: "pypi.org" },
]);
4. 信誉缺陷
Creditient Vault从 Egress 侧车中注入出行证书,同时将真实的秘密从沙盒环境变量,命令,文件和日志中保密. 创建沙盒 credentialProxy 启用,然后通过 sandbox.credentialVault。 。 。 .
const sandbox = await Sandbox.create({
connectionConfig: config,
image: "python:3.11",
networkPolicy: {
defaultAction: "deny",
egress: [{ action: "allow", target: "api.example.com" }],
},
credentialProxy: { enabled: true },
});
await sandbox.credentialVault.create({
credentials: [{ name: "api-token", source: { value: "<token>" } }],
bindings: [
{
name: "api-token",
match: {
schemes: ["https"],
hosts: ["api.example.com"],
paths: ["/v1/*"],
},
auth: { type: "apiKey", name: "x-api-key", credential: "api-token" },
},
],
});
见 证书 用于认证类型、绑定引导和 Git/ curl 示例.
5. 资源清理
两者 Sandbox 财务报告和审定财务报表 SandboxManager 在 Node.js 上运行时, 拥有一个瞄准镜的 HTTP 代理, 这样您可以安全地重用相同的 ConnectionConfig。一旦您完成了与沙盒或管理 API 的交互,请拨 sandbox.close() 编号 : manager.close() 释放潜伏的特工.
浏览器注释
- SDK可以在浏览器中运行,但是 流媒体文件上传为节点。 。 。 .
- 如果你通过了
ReadableStream或者说AsyncIterable页:1writeFiles,浏览器将返回到 在内存中缓冲 上传前. - 原因: 浏览器不支持流线
multipart/form-data有自定义边界的正文(由已执行上传的 API 要求). - 重定向:同源重定向会保留请求头,而跨源重定向会下降
OPEN-SANDBOX-*编号 :OPENSANDBOX-*信头(加)Authorization, (中文(简体) ),Cookie,以及Proxy-Authorization)所以从不重放证书. 文件上传从不跟随重定向. 浏览器无法检查手动重定向目标,所以一个带有被保护头的请求在收到重定向时失败了;Node.js不受影响. 见 重定向和保护标题。 。 。 .