类型脚本的嵌入式沙盒
运行代码在从"节点"(Node.js 20)或后期的孤立多克云沙盒中. 你的Docker账户需要Cloud Sandbox访问.
npm install @docker/sandboxes
签名
SDK给予您的应用程序一个URL和代码以显示用户. 它等待签入,然后将会话保存在记忆中并在需要时刷新.
import { oauth, Sandboxes, SandboxesError } from '@docker/sandboxes';
const auth = oauth({
onVerification({ verificationUriComplete, verificationUri, userCode }) {
console.log(`Open ${verificationUriComplete ?? verificationUri} and enter ${userCode}`);
},
});
await auth.getAccessToken(); // Complete attended sign-in before the first API deadline starts.
const client = new Sandboxes({ auth });
被关注的登录是跟随设备代码的寿命,而不是30秒请求的超时. 个人认证请求仍然有限度。 过 auth.getAccessToken({ signal }) 停止等待; 取消一个呼叫者不会取消共享的登录。 API请求还有自己的期限,所以在制作前完成登录.
OAuth 证书默认会留在内存中,所以一个新的进程再次在其中签名. 对于明显的本地持久性,通过一种有意忽略的路径,例如: store: fileOAuthCredentialStore({path: '.docker-sandboxes/oauth.json'});它存储带有限制性POSIX权限的纯文本证书。 保持路径的源控制。 使用密钥链,加密数据库,或用于生产工作量的秘密管理器.
自定义证书存储器应该尊重所提供的中止信号. SDK在发布新证书或开始另一个保存之前,等待飞行中保存和解.
对于带有多克个人访问符的自动化,使用PAT认证器. 它将 PAT 与 HTTPS 交换为短寿命的访问符,将其保存在内存中,并自动刷新. API验证了符号;SDK读出其过期时只为排程更新.
import { pat } from '@docker/sandboxes';
declare const username: string;
declare const personalAccessToken: string;
const patAuth = pat({ username, personalAccessToken });
const automatedClient = new Sandboxes({ auth: patAuth });
自定义认证传输
如果登录必须使用代理或自定义的 CA 配置, 请将您的获取兼容函数传递到 pat() 或者说 oauth()客户端 fetch 选项只控制 API 请求;它不会重配置共享认证符。 将同一运输方式用于两种情况:
declare const customFetch: (request: Request) => Promise<Response>;
const proxyAuth = pat({
username,
personalAccessToken,
fetch: customFetch,
transportRetries: 'none',
});
const proxyClient = new Sandboxes({
auth: proxyAuth,
fetch: customFetch,
transportRetries: 'none',
});
每个验证器保留其初始登录和刷新时的自定义功能. oauth() 用它来申请设备码 和象征性投票。 该功能必须支持同时提出的请求,尊重请求的中止信号并重定向政策,并且每个呼叫一次尝试. 声明 transportRetries: 'none' 使用自定义获取。 认证会保留其已有的最后期限, 当自定义运输失败时不会重试或返回到全局获取 。 不自定义取用,认证使用平台的全球取用. 关闭客户端不会关闭其验证器或借入的运输.
默认情况下, 同一访问令牌、 令牌提供者或签名会话认证 Sandbox 请求 https://connect.docker.com/sandboxes 个人治理请求 https://hub.docker.com/rpc。签名不会读取或更改 Docker CLI 证书.
继承的环境变量可以改变SDK发送证书的地方. 除非您有意使用内部集成覆盖, 否则不设 SANDBOXES_API_URL, (中文(简体) ), DOCKER_OAUTH_ISSUER, (中文(简体) ), DOCKER_TOKEN_EXCHANGE_URL,以及 DOCKER_GOVERNANCE_URL 在创建客户端或认证器之前.
内部整合超越
这些控制被保留用于内部测试,而不是支持最终用户配置.
| 变量 | 选择 | 默认 |
|---|---|---|
SANDBOXES_API_URL | 管理 API 基础,无 /v1 | https://connect.docker.com/sandboxes |
DOCKER_OAUTH_ISSUER | OAuth 发行器及其设备和符号端点 | https://login.docker.com/ |
DOCKER_TOKEN_EXCHANGE_URL | PAT 交换端点 | https://hub.docker.com/v2/auth/token |
DOCKER_GOVERNANCE_URL | 个人治理RPC基地 | https://hub.docker.com/rpc |
每个被省略的变量都会保留自己的生产默认. 从管理URL中无法推断治理. 覆盖必须是没有用户信息,查询或片段的非空HTTPS URL. 一个管理基础, 以诸如 /v1 拒绝而不是改写.
在构建前设定覆盖 pat(), (中文(简体) ), oauth() 或者说 Sandboxes。每个都保留其初始配置;后来的环境变化不会重定向请求或符号刷新。 使用 Docker 认证器的客户端必须匹配该认证器的管理和治理基础. 明确 baseUrl 优先于 SANDBOXES_API_URL,但不能绕过验证或此权限检查。 为每个发行者使用单独的OAuth证书存储;所存储的记录不约束于发行者.
推荐的证书配置是 auth: 使用 oauth() 以报应者发誓, pat() 用于自动化, bearer() 用于现有访问符或自定义 Authenticator 当应用程序拥有象征性的获取. SandboxesOptions 也支持 accessToken 以固定的记名牌盟誓 tokenProvider 每一个请求都要读出一个符号.
创建沙盒并运行代码
服务器接受请求时创建返回 。 下一步需要运行的沙盒时分别等待; 何时 accepted.status === 'running' 财务报告和审定财务报表 accepted.uid 已经设定,等待只读一遍,你可以使用 accepted 直接说 等你自己过后再等吧 idempotencyKey:再利用的密钥重放原始创建结果,甚至对于一个自此被删除的沙盒来说也是如此. withSandbox() 财务报告和审定财务报表 kits.launchAndWait() 在相同条件下跳过读取。 以后的例子再利用 client 财务报告和审定财务报表 sandbox。 。 。 .
const accepted = await client.create({
imageRef: 'python:3.12',
displayName: 'python-worker',
resources: { cpus: 2, memoryMib: '4096' },
});
const sandbox = await accepted.waitUntilRunning();
const result = await sandbox.processes.run({
args: ['python', '-c', 'print("Hello from a sandbox")'],
});
process.stdout.write(result.stdout);
process.stderr.write(result.stderr);
console.log(result.exitCode);
await sandbox.files.write('/tmp/message.txt', 'Hello\n');
const message = await sandbox.files.read('/tmp/message.txt', { encoding: 'utf8' });
console.log(message);
服务员默认为五分钟. 过 { timeoutMs: 60_000 } 更改最后期限。 超时离开沙盒就位.
使用返回的键 name 重新连接。 列出一个页面或在所有页面上排列 :
const existing = await client.get(sandbox.name);
for await (const item of client.allSandboxes({ query: { pageSize: 25 } })) {
console.log(item.name, item.core.status);
}
Pagination没有默认的总超时;每个页面请求保留其30秒的超时. 明确 timeoutMs 从迭代开始,包括所花时间的加工项目,将整个转接相接. 呼叫者取消、客户端关闭和附加的工作流程截止时间在另一个请求或缓冲项目之前停止 traversal . collect() 财务报告和审定财务报表 listAll*() 在记忆中保留所有结果.
启动捆绑的包
工具包提供沙盒图像及其代理配置. SDK包括一个版本目录; list() 本地读取. 服务器必须支持工具包的发射,被选中的代理商可能需要自己的证书.
console.log(client.kits.list());
const agentSandbox = await client.kits.launchAndWait('claude', {
displayName: 'coding-agent',
resources: 'small',
});
launchAndWait() 创建沙盒,并在一个截止日期内等待运行状态。 使用 launch() 当你需要被接受的手柄 并且会单独等待。 既不启动代理任务, 也不检查套件设置创建的文件 .
Kit 发射默认为 Small (2 vCPU, 4 GiB). 选择 micro, (中文(简体) ), small, (中文(简体) ), medium, (中文(简体) ), large,或 xl 结束 resources,或提供明确的CPU/记忆对象。 同样的命名大小工作 client.create()。 。 。 .
管理个人网络政策
治理使用相同的客户资格. 这些方法管理注册用户所拥有的政策;它们不选择一个组织或另一个用户。 此示例创建了空许可列表 。 加入所需的网络规则后, 才能附加到沙盒中 .
const policy = await client.governance.policies.create({
name: 'project-network',
policyType: 'POLICY_TYPE_ALLOWLIST',
allowlist: { rules: [] },
});
const policies = await client.governance.policies.list();
const currentPolicy = await client.governance.policies.get(policy.id);
const updatedPolicy = await client.governance.policies.update(
policy.id,
{ description: 'Network access for this project' },
{ updateMask: 'description' },
);
await client.governance.policies.delete(policy.id);
要在创建沙盒时使用已有的政策, 请将其ID 传递到 network.policyIds。 。 。 .
处理错误和重试
HTTP 失败 SandboxesError。等待失败时保留最后一个观察到的资源 WaitError.resource。 。 。 .
try {
await client.get(sandbox.name, { timeoutMs: 30_000, maxRetries: 0 });
} catch (error) {
if (!(error instanceof SandboxesError)) throw error;
console.error(error.message, error.requestId);
}
默认最多是另外两次试图在安全无端请求上暂时失败。 被支持的突变每个呼叫得到一个偶能键,在重试时与同体重用. 供应 { idempotencyKey: 'your-request-id' } 以重用整个应用程序中的密钥. maxRetries: 0 禁用用于呼叫或客户端的重试. processes.run(),原始流和治理变异 从来没有重播.
processes.run() 没有默认的总期限; 进程创建和每个输出读取保留其30秒请求超时。 过 { timeoutMs: 300_000 } 以作为约束整个运行的第二个论点,包括创造。 呼叫器取消、客户端关闭和附加的工作流程截止日期也停止了本地等待. run() 不杀死进程; withSandbox() 保留其单独的沙盒清理政策。 创建后,失败保留了进程身份 ResourceWaitError.resource。 。 。 .
sandbox.run(['node', '-v']) 运行一个请求中的短命令到沙盒端点,而不是创建进程并读取其输出。 返回相同的结果没有 process,它永远不会被重播。 命令必须在一次请求超时30秒内完成, 除非你通过 { timeoutMs } 作为它的第三个论点。 在失败,取消或超时后,命令可能已经运行,也可能没有运行. 服务封顶捕获的输出,以及 incomplete 当它被剪断时报告。 使用 processes.run() 对于更长的命令,一个终端,一个标签或会话,或者当您需要之后的过程时.
process.connect() 当您在暂时断开后消耗输出时自动重联。 它在最后一个块交付给您的执行者后恢复,而不重新启动进程或重放输入. 每集复苏片段都有30秒的预算. 设定 { reconnect: false } 或者说 { reconnectTimeoutMs: 60_000 } 在控制回收的第二个论据中。 验证失败, 服务拒绝和无效的输出光标会停止连接 .
连接设置有30秒的超时,但附加的处理会话没有默认的寿命限制. 明确 timeoutMs,中止信号或附加工作流程截止时间仍然适用于整个会话。 一个失败的输入写入可能已经到达进程;在再次发送输入之前检查其状态.
自定义获取执行和借用客户端需要 transportRetries: 'none':首先禁用该运输工具内的任何复试。 每通电话都保留了它选定的证书;SDK从不刷新它来拯救一个飞行中的电话. 在表示拒绝后,后来的独立呼号可以更新所管理的登录或PAT. 检索和服务员使用有效的服务器延迟引导,正好是在最后期限允许的时候.
清理
删除前获取最新资源 。 HTTP 204 确认删除; 否则, 等待返回的资源 。 未解释的404不能确认删除.
const latest = await sandbox.refresh();
const deleting = await latest.delete();
if (deleting) await deleting.waitUntilDeleted();
const latestAgent = await agentSandbox.refresh();
const deletingAgent = await latestAgent.delete();
if (deletingAgent) await deletingAgent.waitUntilDeleted();
await automatedClient.close();
await client.close();
close() 取消客户所有的工作,清理其内幕资质. 它不删除沙盒或取消远程证书.
高级 HTTP 和浏览器的使用
client.api 暴露明确的请求信封。 有条件改为通过 If-None-Match页:1 304 回复改为 undefined。 。 。 . client.api.raw 保留 HTTP 状态和响应头 .
浏览器捆绑支持沙盒管理,处理WebSockets和原始文件读取服务允许跨源请求的地方. 流上和多段传输需要节点.js. 关闭一个进程连接可以解开它而不破坏它的进程 .
见 API 规格 请求字段和支持的操作.