Skip to main content
On this page

卷与快照

持久卷让你可以将区域块存储附加到沙箱中,从而使数据在进程重启和新连接之间得以保留。它们非常适合包缓存、构建产物、SQLite 数据库,或任何需要少量耐久存储但不需要将代码提升为完整 Deno Deploy 应用的工作流。

预配存储 Jump to heading

持久卷目前处于私有测试阶段。如需访问此功能,请联系 support

:::

使用 Client.volumes 预配置存储 Jump to heading

使用管理 Deploy 应用的相同 Client 类。

import { Client } from "@deno/sandbox";

const client = new Client();

const volume = await client.volumes.create({
  slug: "training-cache",
  region: "ord", // 今天仅支持 "ord"(芝加哥)
  capacity: "2GB", // 接受字节数或 "1GB"/"512MB" 之类的字符串
});

console.log(volume);
// {
//   id: "8a0f...",
//   slug: "training-cache",
//   region: "ord",
//   capacity: 2147483648,
//   used: 0
// }
from deno_sandbox import DenoDeploy

sdk = DenoDeploy()

volume = sdk.volumes.create(
  slug="training-cache",
  region="ord",  # 今天仅支持 "ord"(芝加哥)
  capacity="2GB"  # 接受字节数或 "1GB"/"512MB" 之类的字符串
)

print(volume)
# {
#   "id": "8a0f...",
#   "slug": "training-cache",
#   "region": "ord",
#   "capacity": 2147483648,
#   "used": 0
# }
from deno_sandbox import AsyncDenoDeploy

sdk = AsyncDenoDeploy()

volume = await sdk.volumes.create(
  slug="training-cache",
  region="ord",  # 今天仅支持 "ord"(芝加哥)
  capacity="2GB"  # 接受字节数或 "1GB"/"512MB" 之类的字符串
)

print(volume)
# {
#   "id": "8a0f...",
#   "slug": "training-cache",
#   "region": "ord",
#   "capacity": 2147483648,
#   "used": 0
# }
Field Required Details
slug 每个组织内唯一。slug 会成为挂载元数据的一部分,因此请选择有描述性的名称。
region 目前仅支持 "ord"(芝加哥)。只有同一区域中的沙箱才能挂载该卷。
capacity 介于 300 MB 和 20 GB 之间。传入字节数,或带有 GB/MB/KB(十进制)或 GiB/MiB/KiB(二进制)单位的字符串。

检查和搜索卷 Jump to heading

client.volumes.list() 返回分页结果和辅助迭代器,client.volumes.get() 可按 slug 或 UUID 获取单个记录。

const page = await client.volumes.list({ search: "training" });
for (const vol of page.items) {
  console.log(vol.slug, vol.estimatedFlattenedSize, vol.capacity);
}

const vol = await client.volumes.get("training-cache");
page = sdk.volumes.list(search="training")
for vol in page.items:
  print(f"{vol['slug']} {vol['estimatedFlattenedSize']} {vol['capacity']}")

vol = sdk.volumes.get("training-cache")
page = await sdk.volumes.list(search="training")
async for vol in page:
  print(f"{vol['slug']} {vol['estimatedFlattenedSize']} {vol['capacity']}")

vol = await sdk.volumes.get("training-cache")

used 字段报告控制平面从底层集群获得的最新估算值。该值可能会比实际情况滞后几分钟,因此创建卷时请预留足够的容量。

在沙箱内挂载卷 Jump to heading

调用 Sandbox.create() 时传入 volumes 映射。键为挂载路径,值为卷的 slug 或 ID。沙箱和卷必须位于同一区域

Note

Sandbox.create()client.sandboxes.create() 功能相同——根据你的代码风格选择使用即可。

import { Client, Sandbox } from "@deno/sandbox";

const client = new Client();
const volume = await client.volumes.create({
  slug: "dataset",
  region: "ord",
  capacity: "1GB",
});

// 第一次运行时向卷中写入文件
{
  await using sandbox = await Sandbox.create({
    region: "ord",
    volumes: {
      "/data/dataset": volume.slug,
    },
    labels: { job: "prepare" },
  });

  await sandbox.fs.writeTextFile("/data/dataset/hello.txt", "Persist me!\n");
}

// 新沙箱 —— 可能在数小时之后启动 —— 可以读取同一个文件
{
  await using sandbox = await Sandbox.create({
    region: "ord",
    volumes: {
      "/data/dataset": volume.id, // ID 也可用
    },
  });

  const contents = await sandbox.fs.readTextFile("/data/dataset/hello.txt");
  console.log(contents); // "Persist me!"
}
from deno_sandbox import DenoDeploy

sdk = DenoDeploy()

volume = sdk.volumes.create(
  slug="dataset",
  region="ord",
  capacity="1GB"
)

# 第一次运行时向卷中写入文件
with sdk.sandbox.create(
  region="ord",
  volumes={
    "/data/dataset": volume["slug"],
  },
  labels={"job": "prepare"}
) as sandbox:
  sandbox.fs.write_text_file("/data/dataset/hello.txt", "Persist me!\n")

# 新沙箱 —— 可能数小时后启动 —— 可以读取同一个文件
with sdk.sandbox.create(
  region="ord",
  volumes={
    "/data/dataset": volume["id"],  # ID 也可以用
  }
) as sandbox:
  contents = sandbox.fs.read_text_file("/data/dataset/hello.txt")
  print(contents)  # "Persist me!"
from deno_sandbox import AsyncDenoDeploy

sdk = AsyncDenoDeploy()

volume = await sdk.volumes.create(
  slug="dataset",
  region="ord",
  capacity="1GB"
)

# 第一次运行时向卷中写入文件
async with sdk.sandbox.create(
  region="ord",
  volumes={
    "/data/dataset": volume["slug"],
  },
  labels={"job": "prepare"}
) as sandbox:
  await sandbox.fs.write_text_file("/data/dataset/hello.txt", "Persist me!\n")

# 新沙箱 —— 可能数小时后启动 —— 可以读取同一个文件
async with sdk.sandbox.create(
  region="ord",
  volumes={
    "/data/dataset": volume["id"],  # ID 也可以用
  }
) as sandbox:
  contents = await sandbox.fs.read_text_file("/data/dataset/hello.txt")
  print(contents)  # "Persist me!"

挂载点表现得像普通目录。你可以创建子文件夹、写入二进制文件,或直接从卷中执行程序。

安全删除卷 Jump to heading

await client.volumes.delete("training-cache");
sdk.volumes.delete("training-cache")
await sdk.volumes.delete("training-cache")

删除是一个两步过程:

  1. API 会立即将卷标记为删除状态,阻止新沙箱请求挂载它,并释放该 slug 以供将来使用。
  2. 后台任务将在 24 小时后从集群中移除底层块存储。此宽限期允许你在意外删除卷时联系支持。

宽限期内无法挂载或读取该卷。

快照 Jump to heading

快照是从卷创建的只读镜像。当沙箱以快照作为根目录启动时,整个文件系统被快照内容替换。你可以运行一次 apt-get installnpm install,创建快照,然后所有未来的沙箱启动时都会立即拥有预安装的软件。

创建快照的工作流程 Jump to heading

  1. 从基础镜像创建一个可启动卷
  2. 使用该卷作为 root(可写)启动沙箱
  3. 安装软件
  4. 对该卷进行快照

从快照启动的沙箱会立即启动并拥有所有预配置的软件。

当卷用 from 选项创建时即为可启动。目前唯一可用的基础镜像是 builtin:debian-13

import { Client } from "@deno/sandbox";

const client = new Client();

// 1. 创建一个可启动卷
const volume = await client.volumes.create({
  region: "ord",
  slug: "my-toolchain",
  capacity: "10GiB",
  from: "builtin:debian-13",
});

// 2. 启动沙箱,使用该卷作为根目录(可写)
await using sandbox = await client.sandboxes.create({
  region: "ord",
  root: volume.slug,
});

// 3. 安装软件
await sandbox.sh`apt-get update && apt-get install -y nodejs npm`;
await sandbox.sh`npm install -g typescript`;

// 4. 对卷进行快照
const snapshot = await client.volumes.snapshot(volume.id, {
  slug: "my-toolchain-snapshot",
});
>_
# 从卷创建快照
deno sandbox snapshots create my-toolchain my-toolchain-snapshot

从快照启动 Jump to heading

拿到快照后,可用其作为创建新沙箱时的 root。沙箱必须和快照位于同一区域:

await using sandbox = await client.sandboxes.create({
  region: "ord",
  root: "my-toolchain-snapshot", // 快照的 slug 或 ID
});

// TypeScript 和 Node.js 已经安装好
await sandbox.sh`tsc --version`;
await sandbox.sh`node --version`;

沙箱启动时,快照的文件系统作为根目录。会话期间所有写操作都是临时性的,它们不会修改快照。

列出快照 Jump to heading

const page = await client.snapshots.list();
for (const snap of page.items) {
  console.log(snap.slug, snap.region, snap.bootable);
}
>_
$ deno sandbox snapshots list
ID                             SLUG                    REGION   ALLOCATED    BOOTABLE
snp_ord_spmbe47dysccpy277ma6   my-toolchain-snapshot   ord      217.05 MiB   TRUE

从快照创建卷 Jump to heading

从快照创建一个新的可写卷:

const volume = await client.volumes.create({
  region: "ord",
  slug: "my-toolchain-fork",
  capacity: "10GiB",
  from: "my-toolchain-snapshot",
});

新卷包含快照内容且完全可写。你可以用它来修改快照内容然后重新创建快照。

删除快照 Jump to heading

await client.snapshots.delete("my-toolchain-snapshot");
>_
deno sandbox snapshots delete my-toolchain-snapshot

卷 和 快照对比 Jump to heading

特性 卷(Volumes) 快照(Snapshots)
访问权限 读写 只读
挂载点 任意路径,启动卷可用作根目录 仅根文件系统
使用场景 缓存、数据库、安装软件 预安装的软件、工具链
并发使用 同时只能一个沙箱挂载 多个沙箱可以同时使用
区域 必须与沙箱区域匹配 必须与沙箱区域匹配

Last updated on

Did you find what you needed?

编辑此页面
Privacy policy