本地构建的自定义sandbox-extra镜像推送到沙盒daytona的snapshot列表中

Sandbox Extra 镜像推送与升级指南

日期 : 2026-07-02

环境 : Daytona v0.190.0 (Docker Compose 本地部署)

镜像 : sandbox-extra:0.1 (约 5GB / 1.38GB content)

背景:由于daytona默认的镜像不满足自己的需要,于是自己改造了镜像重新打包为sandbox-extra镜像,接下来列出了推送到daytona的snapshot的过程


目录

  1. 整体流程概览
  2. 前置准备与关键参数
  3. [方式一:通过 Daytona API 创建 Snapshot(推荐)](#方式一:通过 Daytona API 创建 Snapshot(推荐) "#3-%E6%96%B9%E5%BC%8F%E4%B8%80%E9%80%9A%E8%BF%87-daytona-api-%E5%88%9B%E5%BB%BA-snapshot%E6%8E%A8%E8%8D%90")
  4. [方式二:通过 Web Dashboard 操作](#方式二:通过 Web Dashboard 操作 "#4-%E6%96%B9%E5%BC%8F%E4%BA%8C%E9%80%9A%E8%BF%87-web-dashboard-%E6%93%8D%E4%BD%9C")
  5. [方式三:通过 Daytona CLI 操作(开发中)](#方式三:通过 Daytona CLI 操作(开发中) "#5-%E6%96%B9%E5%BC%8F%E4%B8%89%E9%80%9A%E8%BF%87-daytona-cli-%E6%93%8D%E4%BD%9C%E5%BC%80%E5%8F%91%E4%B8%AD")
  6. 踩坑记录
  7. 后续升级镜像的标准操作流程
  8. [常见问题 FAQ](#常见问题 FAQ "#8-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-faq")

1. 整体流程概览

flowchart LR A[本地构建镜像<br/>sandbox-extra:0.1] --> B[打Registry标签<br/>localhost:6000/...] B --> C[推送到本地Registry<br/>docker push] C --> D[创建Snapshot<br/>API / Dashboard] D --> E[Runner拉取镜像] E --> F[Snapshot状态: active]

2. 前置准备与关键参数

2.1 环境信息

参数
Daytona API 地址 http://localhost:3000
Registry 地址(宿主机) localhost:6000
Registry 地址(容器内部) registry:6000 ← 关键!
Registry 登录 admin / password
Registry 项目 daytona
组织 ID (Organization ID) 9038b0ab-b214-46d2-a14e-d2113ecf2fd4
Dex OIDC 地址 http://localhost:5556/dex
Web Dashboard http://localhost:3000/dashboard

2.2 认证凭据

yaml 复制代码
Web 登录账号: dev@daytona.io / password
API Key:      dtn_b4b9e38cfcc3677bae7d72dc0812ecf7dacdb5534789e9ce2d1b89bf605d1132

⚠️ 注意 : API Key 默认权限不足以创建 snapshot(返回 403),需要用 JWT Token 认证。


3. 方式一:通过 Daytona API 创建 Snapshot(推荐)

3.1 获取 JWT Token

Daytona 使用 Dex 做 OIDC 认证,可以通过 Device Code FlowWeb 登录 获取 JWT Token。

方法 A:通过 Web 登录获取(最简单)

  1. 打开浏览器访问 http://localhost:3000/dashboard
  2. dev@daytona.io / password 登录
  3. 登录后从浏览器开发者工具中复制 JWT Token:
    • F12 → Application → Local Storage → 找到 token
    • 或者在 API 请求头中复制 Authorization: Bearer xxx

方法 B:通过 Device Code Flow(命令行)

bash 复制代码
# 1. 获取设备认证码
curl -s -X POST http://localhost:5556/dex/device/code \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=daytona&scope=openid%20profile%20email"

# 返回示例:
# { "device_code": "xxx", "user_code": "XXXX-XXXX",
#   "verification_uri_complete": "http://localhost:5556/dex/device?user_code=XXXX-XXXX" }

# 2. 浏览器打开 verification_uri_complete 链接,用 dev@daytona.io 登录

# 3. 轮询获取 token
curl -s -X POST http://localhost:5556/dex/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
  -d "device_code=xxx" \
  -d "client_id=daytona"

3.2 验证 Token

bash 复制代码
# 验证 JWT Token 有效,获取组织 ID
curl -s http://localhost:3000/api/organizations \
  -H "Authorization: Bearer <JWT_TOKEN>" | jq .

# 返回示例:
# [ { "id": "9038b0ab-b214-46d2-a14e-d2113ecf2fd4", "name": "Personal", ... } ]

3.3 推送镜像到本地 Registry

bash 复制代码
# 1. 给镜像打上 Registry 标签
docker tag sandbox-extra:0.1 localhost:6000/daytona/sandbox-extra:0.1

# 2. 推送到本地 Registry
docker push localhost:6000/daytona/sandbox-extra:0.1

验证推送成功:

bash 复制代码
curl -s http://localhost:6000/v2/_catalog | jq .
curl -s http://localhost:6000/v2/daytona/sandbox-extra/tags/list | jq .

3.4 创建 Snapshot

bash 复制代码
TOKEN="<JWT_TOKEN>"
ORG_ID="9038b0ab-b214-46d2-a14e-d2113ecf2fd4"

curl -s -X POST http://localhost:3000/api/snapshots \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Daytona-Organization-ID: $ORG_ID" \
  -d '{
    "name": "sandbox-extra",
    "imageName": "registry:6000/daytona/sandbox-extra:0.1",
    "cpu": 2,
    "memory": 4,
    "disk": 10,
    "sandboxClass": "container"
  }' | jq .

参数说明:

参数 说明 建议值
name Snapshot 名称,唯一标识 sandbox-extra
imageName 容器内部 Registry 地址 registry:6000/daytona/sandbox-extra:0.1
cpu Sandbox 分配的 CPU 核数 2
memory 内存大小 (GB) 4
disk 磁盘大小 (GB) 10
sandboxClass Sandbox 类型 container

3.5 查看 Snapshot 状态

bash 复制代码
curl -s http://localhost:3000/api/snapshots \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Daytona-Organization-ID: $ORG_ID" | jq '.items[] | {name, state, size, errorReason}'

可能的状态流转:

pendingpullingactive ✅ (成功)

pendingpullingerror ❌ (失败,查看 errorReason)

3.6 删除 Snapshot(如需重试)

bash 复制代码
SNAPSHOT_ID="<snapshot-id>"

curl -s -X DELETE "http://localhost:3000/api/snapshots/$SNAPSHOT_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Daytona-Organization-ID: $ORG_ID"

4. 方式二:通过 Web Dashboard 操作

4.1 登录 Dashboard

  1. 浏览器打开 http://localhost:3000/dashboard
  2. 使用 dev@daytona.io / password 登录
  3. Dex 会重定向回 Dashboard

4.2 推送镜像到 Registry(前提)

无论哪种方式,都需要先将镜像推送到本地 Registry:

bash 复制代码
docker tag sandbox-extra:0.1 localhost:6000/daytona/sandbox-extra:0.1
docker push localhost:6000/daytona/sandbox-extra:0.1

4.3 通过界面创建 Snapshot(推测)

⚠️ 注意: 以下内容基于 API 行为推导,实际界面可能略有差异。

  1. 登录 Dashboard 后,找到 Snapshots(快照)管理页面
  2. 点击 Create Snapshot(创建快照)
  3. 填写以下信息:
    • Name : sandbox-extra
    • Image Name : registry:6000/daytona/sandbox-extra:0.1
      • ⚠️ 必须用容器内部地址 registry:6000,不能用 localhost:6000
    • CPU / Memory / Disk: 按需设置
  4. 点击 Create(创建)
  5. 等待状态从 pendingpullingactive

4.4 Registry UI 查看镜像

另外,可以通过 Registry UI 查看已推送的镜像:

  • 地址:http://localhost:5100
  • 可以查看 daytona/sandbox-extra 仓库及其标签

5. 方式三:通过 Daytona CLI 操作(开发中)

Daytona CLI (daytona) 当前版本 (v0.190.0) 主要用于服务端管理和 Sandbox 交互,暂未提供直接的 snapshot 管理命令。

bash 复制代码
# 查看 CLI 当前可用的命令
daytona --help

如果需要从 CLI 操作,可考虑使用 curl 封装脚本(见方式一)。


6. 踩坑记录

坑 1:localhost:6000 vs registry:6000(最重要!)

❌ 错误做法:

bash 复制代码
# 创建 snapshot 时使用了宿主机视角的地址
"imageName": "localhost:6000/daytona/sandbox-extra:0.1"

❌ 报错信息:

vbnet 复制代码
Snapshot localhost:6000/daytona/sandbox-extra:0.1 failed to inspect in registry.
Error: Error response from daemon: Get "http://localhost:6000/v2/":
dial tcp [::1]:6000: connect: connection refused

✅ 正确做法:

bash 复制代码
# 使用 Docker 内部网络的服务名
"imageName": "registry:6000/daytona/sandbox-extra:0.1"

原因分析:

makefile 复制代码
宿主机视角:  localhost:6000  →  可访问 Registry
Runner容器视角:  localhost:6000  →  指向 Runner 自己 (连接被拒绝)
Runner容器视角:  registry:6000  →  Docker DNS 解析到 Registry 容器 (✅)

Runner 会去拉取镜像,所以要用 容器内部网络 的地址。

坑 2:API Key 权限不足

❌ 错误做法:

bash 复制代码
# 直接用 API Key 调用 POST /api/snapshots
Authorization: Bearer dtn_b4b9e38cfcc3677bae7d72dc0812ecf7dacdb5534789e9ce2d1b89bf605d1132

❌ 报错信息:

yaml 复制代码
403 Forbidden: Access denied

原因: 创建 snapshot 需要 write:snapshots 权限,而 API Key 默认可能没有此权限。

✅ 解决方法: 使用 JWT Token(通过 Web 登录获取)代替 API Key。

坑 3:Dex 不支持 password grant type

❌ 错误做法:

bash 复制代码
curl -X POST http://localhost:5556/dex/token \
  -d "grant_type=password&client_id=daytona&username=dev@daytona.io&password=password"

❌ 报错信息:

json 复制代码
{ "error": "unsupported_grant_type" }

原因: Dex 配置中未启用 password grant type,只支持:

  • urn:ietf:params:oauth:grant-type:device_code(设备码)
  • urn:ietf:params:oauth:grant-type:token-exchange(令牌交换)

✅ 解决方法: 通过 Web 登录获取 JWT,或使用 Device Code Flow。

坑 4:相同的 name 不能重复创建

第一次失败后需要先删除再重新创建,否则创建会失败。


7. 后续升级镜像的标准操作流程

当构建了新的 sandbox-extra:0.2(或更新版本)时,按以下步骤操作:

Step 1: 构建新版本镜像

bash 复制代码
# 在你的构建目录下
cd /root/daytona-sandbox-extra
./build.sh          # 或其他构建命令

Step 2: 推送新版本到 Registry

bash 复制代码
# 打标签
docker tag sandbox-extra:0.2 localhost:6000/daytona/sandbox-extra:0.2

# 推送到 Registry
docker push localhost:6000/daytona/sandbox-extra:0.2

Step 3: 通过 Dashboard 创建新 Snapshot

  1. 登录 http://localhost:3000/dashboard
  2. 进入 Snapshots 管理页面
  3. 点击 Create Snapshot
  4. 填写:
    • Name : sandbox-extra-v2(或不同的名称)
    • Image Name : registry:6000/daytona/sandbox-extra:0.2
    • Resource: 按需设置
  5. 点击创建,等待状态变为 active

Step 4(可选): 通过 API 创建

bash 复制代码
JWT="<你的JWT Token>"
ORG_ID="9038b0ab-b214-46d2-a14e-d2113ecf2fd4"

curl -s -X POST http://localhost:3000/api/snapshots \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -H "X-Daytona-Organization-ID: $ORG_ID" \
  -d '{
    "name": "sandbox-extra-v2",
    "imageName": "registry:6000/daytona/sandbox-extra:0.2",
    "cpu": 2,
    "memory": 4,
    "disk": 10,
    "sandboxClass": "container"
  }' | jq .

完整一键脚本

bash 复制代码
#!/bin/bash
# file: /root/daytona/docker/push-sandbox-extra.sh

set -e

VERSION="${1:-0.1}"
JWT="$JWT_TOKEN"          # 先 export JWT_TOKEN=...
ORG_ID="9038b0ab-b214-46d2-a14e-d2113ecf2fd4"

echo "=== 1. 打标签 ==="
docker tag sandbox-extra:${VERSION} localhost:6000/daytona/sandbox-extra:${VERSION}

echo "=== 2. 推送镜像 ==="
docker push localhost:6000/daytona/sandbox-extra:${VERSION}

echo "=== 3. 创建 Snapshot ==="
curl -s -X POST http://localhost:3000/api/snapshots \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -H "X-Daytona-Organization-ID: $ORG_ID" \
  -d "{
    \"name\": \"sandbox-extra-v${VERSION}\",
    \"imageName\": \"registry:6000/daytona/sandbox-extra:${VERSION}\",
    \"cpu\": 2,
    \"memory\": 4,
    \"disk\": 10,
    \"sandboxClass\": \"container\"
  }" | jq .

echo "=== 4. 等待拉取完成 ==="
sleep 5
curl -s http://localhost:3000/api/snapshots \
  -H "Authorization: Bearer $JWT" \
  -H "X-Daytona-Organization-ID: $ORG_ID" | jq '.items[] | {name, state, size, errorReason}'

使用方法:

bash 复制代码
export JWT_TOKEN="eyJxxxxx"
bash /root/daytona/docker/push-sandbox-extra.sh 0.2

8. 常见问题 FAQ

Q: 创建 snapshot 后一直卡在 pending 状态?

A: 检查 runner 是否正常运行:docker ps | grep runner。runner 负责拉取镜像。

Q: 状态变为 error,错误信息包含 "connection refused"?

A: 镜像地址使用了 localhost:6000,应改为 registry:6000。详见 [坑 1](#坑 1 "#%E5%9D%91-1localhost6000-vs-registry6000%E6%9C%80%E9%87%8D%E8%A6%81")。

Q: API 返回 401 Unauthorized?

A: Token 可能已过期。JWT Token 有效期约 24 小时,过期后重新通过 Web 登录获取。

Q: API 返回 403 Forbidden?

A: 改用 JWT Token 而不是 API Key。详见 [坑 2](#坑 2 "#%E5%9D%91-2api-key-%E6%9D%83%E9%99%90%E4%B8%8D%E8%B6%B3")。

Q: 如何获取 Organization ID?

A: 调 GET /api/organizations 接口:

bash 复制代码
curl -s http://localhost:3000/api/organizations \
  -H "Authorization: Bearer $JWT" | jq '.[0].id'

Q: Registry 里有哪些镜像?

A: 通过 Registry API 查看:

bash 复制代码
# 查看所有仓库
curl -s http://localhost:6000/v2/_catalog | jq .

# 查看特定仓库的标签
curl -s http://localhost:6000/v2/daytona/sandbox-extra/tags/list | jq .

Q: 如何查看 Runner 的日志排查问题?

A: docker logs daytona-runner-1 --tail 50


最后更新: 2026-07-02 | Daytona v0.190.0 | Docker Compose 部署

相关推荐
网易云信1 小时前
Agent在客服和营销领域走到哪一步了?深度解析3个挑战和5大趋势
人工智能·agent
网易云信2 小时前
AI 融入协作场景,Hermes 接入云信 IM
人工智能·agent
vivo互联网技术2 小时前
ICLR 2026 | 基于后验采样的图像恢复方法LearnIR:人脸去阴影、去雾
人工智能·算法·aigc
饼干哥哥2 小时前
ChatGPT会员掉了,代充黑幕藏不住了
人工智能·操作系统·产品
ZzT2 小时前
Claude Sonnet 5 来了:Opus 级的能力,Sonnet 的价
人工智能·ai编程·claude
用户5191495848453 小时前
CVE-2025-14440 漏洞利用工具 - WordPress 插件认证绕过检测
人工智能·aigc
网易云信3 小时前
网易智企亮相2026上海文创展:重新定义文创潮玩的“生命力”
人工智能·产品
魏祖潇3 小时前
DDD、TDD、SDD——AI 时代工程师的三件秩序乐器
人工智能·ai编程
Bigfish_coding3 小时前
前端转agent-【python】-18 Agent 与本地应用结合:让 AI 操作你的浏览器
人工智能