跳转到内容
返回主页

自定义镜像模板

模板定义沙箱启动时使用的镜像、资源、环境变量、启动行为、就绪检查和存储挂载。

首次接入优先使用官方模板。重复安装和启动逻辑稳定后,再构建自定义模板。

以下情况适合构建自定义模板:

  • 依赖只安装一次,而不是每次沙箱启动都安装
  • 将源码复制进可复用镜像
  • 固定 OS 包和语言包版本
  • 定义 startCmdreadyCmd
  • 通过模板策略挂载持久存储路径
  • 通过 stableprod 等标签推广已验证构建
目标建议起点
Shell 命令和文件操作base
代码解释器和数据分析code-interpreter
Node 前端或 API 服务nodeweb-frontend
Python 服务或脚本python
浏览器自动化browser
持久工作区nfscloudblock 或自定义 tpl-...
生产可复现具体 tpl-...
import { Sandbox, Template, waitForPort } from "@seacloudai/sandbox";
const built = await Template.build(
new Template()
.fromNodeImage("20-alpine")
.copy("./my-app", "/app", { forceUpload: true })
.runCmd("cd /app && npm install")
.runCmd("cd /app && npm run build")
.setStartCmd("cd /app && npm start", waitForPort(3000)),
"my-app:v1",
{ wait: true },
);
const app = await Sandbox.create(built.templateId, { waitReady: true });
console.log(app.getHost(3000));
  1. 通过 POST /api/v1/templates 创建模板元数据。
  2. 将本地源码打包为 .tgz
  3. 通过构建上下文握手上传归档文件。
  4. 调用 /api/v1/templates/:templateID/builds/:buildID 启动构建。
  5. 轮询状态直到 ready
  6. 使用返回的 templateID 创建沙箱。

公开构建流程会按 hash 对本地源码归档去重。

GET /api/v1/templates/:id/files/:hash
X-API-Key: <token>

响应可能包含签名上传 URL 和 maxContextBytes

{
"present": false,
"url": "https://storage.googleapis.com/...",
"maxContextBytes": 104857600
}

默认单个归档上限为 100MiB。上传前应排除 .gitnode_modulesdist.next、缓存目录和生成产物。

状态含义
uploaded等待引用的构建上下文上传。
waiting构建已接收并排队。
building构建任务正在运行。
ready构建完成,模板镜像可用。
error构建失败。

构建状态响应可能包含 timelinestepslogslogEntriesreason。进度 UI 优先使用 timelinesteps,详情再展示日志。

标签是构建版本指针。my-template:stable 会解析到 stable 标签绑定的构建镜像,而不一定是模板当前最新的 currentBuildId

POST /api/v1/templates/tags
X-API-Key: <token>
Content-Type: application/json
{
"target": "my-template:v1",
"tags": ["stable", "prod"]
}

公开构建接口当前接收结构化构建步骤,而不是原始 Dockerfile 文本。

Dockerfile 指令构建 payload
FROM node:20fromImage: "node:20" 或官方基础模板引用
WORKDIR /appWORKDIR step
COPY . /appfilesHashCOPY step
RUN npm installRUN step
ENV NODE_ENV=productionENV step
CMD npm startstartCmd
Mode含义
managednano-executor 运行时 API 可在运行时端口访问,通常是 9000
plain镜像自己拥有前台应用进程;nano-daemon 仍可提供探针和心跳。

workdir 控制默认进程和文件根目录,但不创建持久存储。存储拓扑来自模板 volumeMounts

使用 startCmd 为未来从该模板创建的沙箱启动长运行应用进程。使用 readyCmd 判断沙箱是否已经可用。

好的就绪检查应该是本地、有限时长,并且和用户会打开的端口一致:

Terminal window
wget -q -O- http://127.0.0.1:3000/ >/dev/null

避免只证明进程存在、但不能证明应用可用的检查:

Terminal window
ps aux | grep node

startCmdreadyCmd 使用 shell 语义。镜像应包含 /bin/sh,或命令应按该镜像可用的 shell 编写。

模式建议
HTTP 应用startCmd 启动服务;readyCmd curl 本地应用端口。
后台 WorkerreadyCmd 检查健康文件、PID、队列连接或 worker 心跳。
前端预览绑定 0.0.0.0readyCmd 检查 127.0.0.1:<port>;用户打开 getHost(port)
重依赖安装把安装步骤放入构建 RUN,不要放在沙箱启动阶段。
现象检查项
构建停在 uploaded归档未上传、filesHash 变化,或上传完成前启动构建。
COPY filesHash is required每个使用本地源码的 COPY 步骤都需要 filesHash
沙箱启动但预览返回 502startCmd 退出、端口错误,或应用只绑定 localhost。
readyCmd 超时沙箱内部目标 localhost 端口没有响应。