@chamvi/sandbox-docker

中文文档
0.8.0发布于 2026/11/09Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 2634

Chamvi的多克沙盒提供商:每个工作空间一个硬化容器.

中文使用文档
文档目录11 节
  1. 安装
  2. 使用量
  3. 集装箱
  4. 图像
  5. 缓存
  6. 警卫
  7. 暂停和中止
  8. 垃圾收集
  9. 选项
  10. API 密码
  11. 许可证

@chamvi/sandbox-docker

@ chamvi/ sandbox-docker (中文(简体) )

每个工作空间一个容器,一个Docker主机上的chamvi代理.
根入内地,所以 apt 和每个软件包管理器工作; 严格在边缘: 少数能力, no-new-privileges, (中文(简体) ),
cpu, 内存和pid限制, 没有主机挂载但包缓存, GNU 内的所有命令 timeout。 。 。 .

npm version CI License


目录

安装

npm install @chamvi/sandbox-docker @chamvi/sandbox @chamvi/core ai --save

仅限无害环境管理,节点.js >=26.0.0。 。 。 . @chamvi/core 财务报告和审定财务报表 @chamvi/sandbox 是同伴的依赖关系。 Docker API 通过 夹层 5(与 @types/dockerode,因为选项需要 Dockerode 客户端); 它拉入 docker-modem, (中文(简体) ), tar-fs, (中文(简体) ), @balena/dockerignore 和 gRPC 软件包 @grpc/grpc-js, (中文(简体) ), @grpc/proto-loader 财务报告和审定财务报表 protobufjs 作为自己的依附关系. 烟雾 是唯一的运行时间依赖.

使用量

import type { ISandboxProvider } from '@chamvi/sandbox';
import { createDockerSandbox } from '@chamvi/sandbox-docker';

export function createSandbox(): ISandboxProvider {
    // DOCKER_HOST or /var/run/docker.sock; nothing connects before the first create()
    return createDockerSandbox({
        network: 'bridge',
        limits: { memory: '1Gi' },
    });
}

把提供者传给 createWorkspaceManager({ provider }) 从 @chamvi/sandbox创建它;第一个 create() 已经.

集装箱

每个工作空间都是容器 chamvi-ws-<id>数字 :

设置数值
用户user默认值 0:0 (单位:千美元)DEFAULT_USER),也是每个命令中的
命令sh -c 睡觉直到 expiresAt (绝对期限,所以一个容器) find 在一个主机或守护进程重新启动后再次启动, 仍然在同一时间停止, 或者一次结束, 图像的切入点被替换( nameEntrypoint: []:容器本身停止在 expiresAt 即使没有收藏, 垃圾收藏也会移除
输入Init: true:docker-init是pid 1,并收获任何图像的孤儿过程(背景工作,一个执行超时的树木杀死),同样是没有init的,否则僵尸会填满的 PidsLimit
根文件系统可写;仅读取 readOnlyRoot
能力全部删除; root 用户返回 CHOWN, (中文(简体) ), DAC_OVERRIDE, (中文(简体) ), FOWNER, (中文(简体) ), FSETID, (中文(简体) ), SETUID, (中文(简体) ), SETGID, (中文(简体) ), KILL (单位:千美元)ROOT_CAPABILITIES(三); no-new-privileges:true没有特权
限制NanoCpus 从 cpu, (中文(简体) ), Memory 财务报告和审定财务报表 MemorySwap (不交换)从 memory, (中文(简体) ), PidsLimit 从 pids
/workspace匿名量,随容器去除(remove({ force: true, v: true })(中文(简体) )
/home/sandbox家庭(WORKSPACE_HOME: 磁盘上的匿名音量, 保存在重启时, 用容器取出
/cache其自己的匿名体积,用容器取出 cache: { volume } 名称的音量,每个工作区都使用它
/tmpa 吨数 tmpSize (默认 1 GiB, TMP_SIZE· ; exec, (中文(简体) ), nosuid, (中文(简体) ), nodev(中文(简体) )
网络network (默认) bridge(中文(简体) )
环境SANDBOX_ENV,缓存变量(CACHE_ENV和 env,没有来自主机
标签app.kubernetes.io/managed-by=chamvi, (中文(简体) ), app.kubernetes.io/component=sandbox, (中文(简体) ), chamvi.dev/run=<runId>, (中文(简体) ), chamvi.dev/workspace=<id>, (中文(简体) ), chamvi.dev/deployment=<deployment>, (中文(简体) ), chamvi.dev/repo-key=<hash> (有一个仓库), chamvi.dev/created-at 财务报告和审定财务报表 chamvi.dev/expires-at (划时代), chamvi.dev/repo, (中文(简体) ), chamvi.dev/ref, (中文(简体) ), chamvi.dev/image

limits.storage 不被执行:默认音量没有大小(使用有配额的存储驱动程序,或Kubernetes供应商)。 命令通过 Docker exec API 在 /workspace; 文件读取时使用 cat 并用 head -c 从斯丁.

硬化模式数字 : createDockerSandbox({ user: '1000:1000', readOnlyRoot: true }) 给出早期版本的容器:uid 1000,一个只读取的根,根本没有能力. apt 和 root 安装则失败; 工具链仍然以 mise 安装入 Home 。 在退出前, 提供者向该用户打开缓存( 一个执行器作为根, 它拥有挂载点 Docker 使图像不包含) /cache,所以它会 /cache 和空顶层 CACHE_ENV 文件夹可以写, 没有任何功能, 因此任何图像都在那里工作 。 只有这些文件夹: root 工作空间会让 root 拥有的文件夹深入到缓存中( npm's) _cacache) 硬化的用户不能写,所以永远不要指非根 user 以美元计 cache.volume 一个 root 工作空间或另一个用户所写 .

图像

默认图像是 ghcr.io/chamvi/sandbox-dev:trixie (单位:千美元)DEFAULT_SANDBOX_IMAGE:德比安克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克, tini 财务报告和审定财务报表 爱,在运行时安装任何工具链(mise use -g node@26, (中文(简体) ), mise install为 linux/amd64 财务报告和审定财务报表 linux/arm64 从 images/sandbox-dev标记 : trixie (根据更改和每周重建)和 trixie-<short sha> (每个承诺一次,改变图像).

  • 运行可能选择一个图像( Q)create_workspace({ image })),只有当管理者有许可列表时(allowImage,或 CHAMVI_SANDBOX_IMAGES 内 sandboxModule())),没有一个工具就没有 image 参数.
  • pull: 'missing' (默认)拉出一幅图像 当守护进程缺少它, 'always' 在每一个创建之前(一个可变的标记,然后是它的重建), 'never' 从来没有。 它覆盖每个图像: 提供者的,经理的 image 和一次运行要求(create_workspace({ image })) (中文(简体) ).
  • 在生产中粘接一个文摘(image: 'ghcr.io/chamvi/sandbox-dev@sha256:...'),或使用 pull: 'always'。 。 。 .
  • 图像的切入点被替换,所以其切入点为命令的图像(["git"]) 工作也一样.
  • 图像需要 sh, (中文(简体) ), git 和一个 GNU timeout 这需要 -k附加时 cat, (中文(简体) ), head, (中文(简体) ), mkdir, (中文(简体) ), dirname, (中文(简体) ), cp, (中文(简体) ), mv 财务报告和审定财务报表 rm。 。 。 . create 探测集装箱运行后前三个故障 SandboxError 在任何检出前(并去掉容器),指定缺少的内容.

缓存

每个工作空间都挂起 /cache 获得 XDG_CACHE_HOME, (中文(简体) ), npm_config_cache, (中文(简体) ), PIP_CACHE_DIR, (中文(简体) ), GOMODCACHE, (中文(简体) ), GOCACHE 财务报告和审定财务报表 COMPOSER_CACHE_DIR 指着它CACHE_ENV: 包只下载,从不使用工具链(将它的安装保存在Home,每个工作空间). 默认 /cache 是一个匿名的音量,每个工作空间,用它删除.

cache: { volume: 'chamvi-cache' } 在每个工作空间中挂载一个命名的音量, 因此同一软件包的第二个安装速度快; 它比每个工作空间都活取它( 用 docker volume rm 以重设). 风险:共享量是每个运行和代理在主机上共享的信任边界. 一个被抓取的恶意包可以坐到另一个运行的缓存; npm 验证完整性的散列, pip, Go 的构建缓存等更少. 只在彼此信任的运行之间共享一卷,每个信任级别共享一卷.

警卫

  • 套接字访问为主机上根. 谁能和Docker套接字说话 可以启动一个特权的容器。 给 chamvi 进程一个 套接字代理服务器 只允许容器、执行和图像,或运行 无根嵌入器,而不是安装 /var/run/docker.sock 进入它.

  • 不是网络边界. 打开 bridge 一个工作空间到达主机网关(chamvi API、Postgres、MCP服务器)、其他容器和云元数据 169.254.169.254。使用一个没有集装箱间交通的专用网络并设置防火墙:

    docker network create --opt com.docker.network.bridge.enable_icc=false chamvi-sandbox
    # then drop traffic from that bridge to the host gateway and 169.254.169.254 (iptables DOCKER-USER chain)
    

    通过 network: 'chamvi-sandbox'。 。 。 . network: 'none' 完全切断网络;然后只有无回放的工作空间才能工作,因为克隆人运行在容器内.

  • 根入于内,不取于主. 一个工作空间在默认情况下以可写入的根文件系统作为根运行, 这样它就可以安装任何东西; 它仍然没有特权的容器, 只持有软件包管理器所需的能力, 保存 no-new-privileges 不挂载任何宿主 cache.volume 是工作空间之间唯一共享的音量。 使用硬化模式( E)user, (中文(简体) ), readOnlyRoot) 容器中的根过多.

  • 即时注射:模型所运行的跟随其读取的. 缩小 allowRepo 在经理和设置 bash 背后的核准 必要时.

暂停和中止

每个命令运行为 timeout -k 5 <seconds> <argv>; GNU 数据 timeout 所以背景背景的孙子孙子也走了 客户端警卫停止等待15秒EXEC_GRACE_MS)在超时后,报告出口137个,产出至今. 一个在背景工作开始时退出的命令,它用自己的退出代码在退出后持有大约2 s的输出返回.

中止( E)signal(中文(简体) ) 节点:多克克洛德从执行溪流中流出,命令一直持续到其 timeout 火灾或工作空间被处理。 每一次确定运行都会处理其工作空间(manager.attach(engine)),所以没有什么比跑步要长。 一个处理器会清除容器, 它杀死任何仍在运行.

一个创造 signal (由 release(runId) 财务报告和审定财务报表 manager.close()) 放弃其请求:图像牵引(守护进程可能自行完成),容器创建(无论怎样制作的守护进程都被移除)并启动. dockerode 默认不设置请求超时,所以挂起的守护进程会拖住一个创建或去除. manager.close() 之后放弃 timeoutMs (30 s) 并报告所剩的; 将每个请求绑定, 通过一个客户端, 暂停 : createDockerSandbox({ docker: new Docker({ timeout: 60_000 }) }) (以ms计,比您最慢的图像拉长).

垃圾收集

find(runId, { deployment }) 通过标签列出运行的容器, 再次启动一个被停止的容器( 主机或守护进程重新启动或中止; 其音量仍然保留着工作) , 也有一个被这个进程控住并发现丢失( 管理者忘记了一个已消失的工作空间而不是处理它) , 并且从标签中重建工作空间, 因此运行在重启后或在共享守护进程的另一复制件上找到其工作空间 . collectGarbage({ deployment, isSettled }) 将部署的容器与管理的标签一并列出,并逐一取出 chamvi.dev/expires-at 并,与 isSettled,其中,已结算运行的运行(此流程的开放工作空间首先被处理),包括崩溃流程和其他共享守护进程复制的运行。 与 suspend: true 财务报告和审定财务报表 isSuspendable 它会停止(从不去除)运行中等待足够长的运行容器,所以它们没有CPU或内存;下一个 find 以文件再次启动它们( e)/tmp 并失去背景工作)。 无 suspend (默认)没有容器被停止:一个沉睡的容器在多克身上没有任何保留. A 类 find 与 restore: false (经理释放) 开始无; 它的手柄只处理. 经理打来的 acquire 最多10分钟一次 无法拆卸的容器不会阻止通行:其他人走,一个 SandboxError 与计数和第一个失败 投出在结尾.

选项

createDockerSandbox(options?)数字 :

选项类型默认说明
dockerDockerodenew Docker()客户( A)DOCKER_HOST 或者说 /var/run/docker.sock(中文(简体) )
imagestringDEFAULT_SANDBOX_IMAGE工作空间图像; 在生产中刻入摘要
networkstring'bridge''bridge', (中文(简体) ), 'none' 或用户创建的网络
pull'missing' | 'always' | 'never''missing'何时拉出图像( 每个图像, 一个运行请求)
envRecord<string, string>无之后添加 SANDBOX_ENV 财务报告和审定财务报表 CACHE_ENV
limitsSandboxLimitsDEFAULT_LIMITScpu, (中文(简体) ), memory, (中文(简体) ), pids, (中文(简体) ), maxLifetimeMs (单位:千美元)storage 未执行)
userstring'0:0'集装箱用户(uid:gid 或名称);非源用户没有能力
readOnlyRootbooleanfalse只读的根文件系统
cache{ volume: string }无(每个工作区匿名量)一个名字 /cache 每个工作空间共享的体积( e)false 财务报告和审定财务报表 {} 拒绝)
suspendbooleanfalse停止收集中长期等待的容器(CHAMVI_SANDBOX_DOCKER_SUSPEND 与 sandboxModule()(中文(简体) )
tmpSizestring'1Gi'面积 /tmp tmpfs 缩写
clockIClocksystemClock过期和执勤警卫

配置错误抛出核心 InvalidAgentDefinitionError; 守护进程和容器失败 SandboxError编号.

API 密码

导出仁爱目的
createDockerSandbox函数这个 ISandboxProvider (单位:千美元)name: 'docker'(中文(简体) )
DEFAULT_NETWORK常数'bridge'
CONTAINER_NAME_PREFIX常数'chamvi-ws-'
DEFAULT_USER常数'0:0'

类型 : DockerSandboxOptions。 。 。 .

许可证

原载 Apache 许可证 2.0。 。 。 .

版本与发布记录

@chamvi/sandbox-docker 共发布 15 个版本,首次发布于 2026/10/25;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.8.0latest2026/11/09今天
0.7.32026/11/063 天前
0.7.22026/11/054 天前
0.7.12026/11/054 天前
0.7.02026/11/045 天前
0.6.12026/11/045 天前

关于 @chamvi/sandbox-docker 的常见问题

@chamvi/sandbox-docker 是什么?

Chamvi的多克沙盒提供商:每个工作空间一个硬化容器.

如何安装 @chamvi/sandbox-docker?

在项目目录运行 npm install @chamvi/sandbox-docker,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@chamvi/core(^0.8.0)、@chamvi/sandbox(^0.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@chamvi/sandbox-docker 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chamvi/sandbox-docker 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chamvi/sandbox-docker 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=26.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chamvi/sandbox-docker 可以商用吗?

@chamvi/sandbox-docker 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@chamvi/sandbox-docker 的下载量有多少?

根据 npm 官方下载统计,@chamvi/sandbox-docker 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,634 次,日均约 88 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chamvi/sandbox-docker 还在维护吗?

最新版本 0.8.0 发布于 2026/11/09(今天);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/10/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。