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(芝加哥)或 ams(阿姆斯特丹)
  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 (芝加哥) 或 ams (阿姆斯特丹)
  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 (芝加哥) 或 ams (阿姆斯特丹)
  capacity="2GB"  # 接受字节数或 "1GB"/"512MB" 样式的字符串
)

print(volume)
# {
#   "id": "8a0f...",
#   "slug": "training-cache",
#   "region": "ord",
#   "capacity": 2147483648,
#   "used": 0
# }
字段 是否必需 详情
slug 在组织内唯一。Slug 会成为挂载元数据的一部分,请选择描述性强的名称。
region 必须匹配可用的沙箱区域(目前为 "ord""ams")。只有同一区域的沙箱才能挂载该卷。
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)
访问权限 读写 只读
挂载点 任意路径,启动卷可用作根目录 仅根文件系统
使用场景 缓存、数据库、安装软件 预安装的软件、工具链
并发使用 同时只能一个沙箱挂载 多个沙箱可以同时使用
区域 必须与沙箱区域匹配 必须与沙箱区域匹配

你找到了你需要的东西吗?

编辑此页面
隐私政策