如何将本地自定义sandbox-extra镜像推送到Daytona沙盒Snapshot列表
本地构建sandbox-extra镜像后推送至Registry,通过API或WebDashboard创建Snapshot。关键注意容器内部网络需使用registry:6000地址,避免连接拒绝;需用JWTToken而非APIKey获取权限;Dex不支持密码模式,需通过Web或设备码认证。相同名称不可重复创建,失败需先删除。
Sandbox Extra 镜像推送与升级指南
在搭建好 Daytona 环境之后,下一个关键动作就是把自定义的 Sandbox Extra 镜像推送上去并创建 Snapshot。这事儿说复杂不复杂,但里面的坑确实不少——尤其是当你从宿主机视角切换到容器内部网络视角的时候,稍不留神就会遇到“连接被拒绝”的报错。
这篇文章会把整个流程拆开来讲,包括三种不同的操作方式、四个典型踩坑记录,以及后续升级镜像的标准操作流程。无论你是第一次操作还是需要排查问题,应该都能找到答案。
1. 整体流程概览
先在大脑里过一遍整体链路:
- 本地构建好
sandbox-extra:0.1镜像 - 给它打上 Registry 标签(
localhost:6000/...) - 通过
docker push推送到本地 Registry - 通过 API 或 Web Dashboard 创建 Snapshot
- Runner 从 Registry 拉取镜像,Snapshot 状态变为
active
整个流程看起来清晰,但关键点在于:Runner 所在的容器网络里,Registry 地址怎么写。这一点会在后面的“踩坑记录”里详细展开。
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 认证凭据
Web 登录账号:dev@daytona.io / password
API Key:dtn_b4b9e38cfcc3677bae7d72dc0812ecf7dacdb5534789e9ce2d1b89bf605d1132
3. 方式一:通过 Daytona API 创建 Snapshot(推荐)
如果你习惯用命令行操作,这种方式是最灵活的。
3.1 获取 JWT Token
Daytona 使用 Dex 做 OIDC 认证,获取 JWT Token 有两种方式。

方法 A:通过 Web 登录获取(最简单)
- 打开浏览器访问
http://localhost:3000/dashboard - 用
dev@daytona.io/password登录 - 登录后从浏览器开发者工具中复制 JWT Token:
- F12 → Application → Local Storage → 找到 token
- 或者在 API 请求头中复制
Authorization: Bearer xxx
方法 B:通过 Device Code Flow(命令行)
第一步,获取设备认证码:
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"
第二步,浏览器打开返回的 verification_uri_complete 链接,用 dev@daytona.io 登录。第三步,轮询获取 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
拿到 JWT Token 后,先验证一下是否有效,顺便确认组织 ID:
curl -s http://localhost:3000/api/organizations \
-H "Authorization: Bearer " | jq .
返回的示例:[ { "id": "9038b0ab-b214-46d2-a14e-d2113ecf2fd4", "name": "Personal", ... } ]
3.3 推送镜像到本地 Registry
docker tag sandbox-extra:0.1 localhost:6000/daytona/sandbox-extra:0.1
docker push localhost:6000/daytona/sandbox-extra:0.1
3.4 创建 Snapshot
这是核心步骤,注意 imageName 字段使用的是容器内部的 Registry 地址:
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 状态
curl -s http://localhost:3000/api/snapshots \
-H "Authorization: Bearer $TOKEN" \
-H "X-Daytona-Organization-ID: $ORG_ID" | jq '.items[] | {name, state, size, errorReason}'
状态流转很清楚:pending → pulling → active(成功),或者 pending → pulling → error(失败,查看 errorReason)。
3.6 删除 Snapshot(如需重试)
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 操作
如果你更倾向于图形界面操作,Dashboard 也完全可以完成。
4.1 登录 Dashboard
浏览器打开 http://localhost:3000/dashboard,使用 dev@daytona.io / password 登录。Dex 会重定向回 Dashboard。
4.2 推送镜像到 Registry(前提)
无论哪种方式,都需要先将镜像推送到本地 Registry:
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
登录 Dashboard 后,找到 Snapshots(快照)管理页面。点击 Create Snapshot(创建快照),填写以下信息:
- Name:
sandbox-extra - Image Name:
registry:6000/daytona/sandbox-extra:0.1(⚠️ 必须用容器内部地址registry:6000) - CPU / Memory / Disk: 按需设置
点击 Create 后,等待状态从 pending → pulling → active 即可。
4.4 Registry UI 查看镜像
通过 http://localhost:5100 可以查看 Registry UI,确认 daytona/sandbox-extra 仓库及其标签是否已经推送成功。
5. 方式三:通过 Daytona CLI 操作(开发中)
Daytona CLI(daytona)当前版本(v0.190.0)主要用于服务端管理和 Sandbox 交互,暂未提供直接的 snapshot 管理命令。可以通过 daytona --help 查看可用命令。如果需要从 CLI 操作,建议使用 curl 封装脚本(见方式一)。
6. 踩坑记录
实际操作中,下面这几个坑几乎是绕不过去的,提前了解一下能节省不少排查时间。
坑 1:localhost:6000 vs registry:6000(最重要!)
❌ 错误做法:
"imageName": "localhost:6000/daytona/sandbox-extra:0.1"
报错信息:
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
✅ 正确做法:
"imageName": "registry:6000/daytona/sandbox-extra:0.1"
原因分析:
宿主机视角下,localhost:6000 可以访问到 Registry。但 Runner 跑在容器里,localhost:6000 指向的是 Runner 容器本身,而 Runner 自己显然没有 Registry 服务,所以连接被拒绝。正确的方式是使用 Docker DNS 内部网络的服务名 registry,这样容器间才能正常通信。
坑 2:API Key 权限不足
❌ 错误做法: 直接用 API Key 调用 POST /api/snapshots
Authorization: Bearer dtn_b4b9e38cfcc3677bae7d72dc0812ecf7dacdb5534789e9ce2d1b89bf605d1132
报错信息:403 Forbidden: Access denied
原因: 创建 snapshot 需要 write:snapshots 权限,而 API Key 默认可能没有此权限。✅ 解决办法:使用 JWT Token(通过 Web 登录获取)代替 API Key。
坑 3:Dex 不支持 password grant type
❌ 错误做法:
curl -X POST http://localhost:5556/dex/token \
-d "grant_type=password&client_id=daytona&username=dev@daytona.io&password=password"
报错信息:{ "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: 构建新版本镜像
cd /root/daytona-sandbox-extra
./build.sh
Step 2: 推送新版本到 Registry
docker tag sandbox-extra:0.2 localhost:6000/daytona/sandbox-extra:0.2
docker push localhost:6000/daytona/sandbox-extra:0.2
Step 3: 通过 Dashboard 创建新 Snapshot
登录 http://localhost:3000/dashboard → 进入 Snapshots 管理页面 → 点击 Create Snapshot → 填写 Name(如 sandbox-extra-v2)、Image Name(registry:6000/daytona/sandbox-extra:0.2)、资源配额 → 创建,等待状态变为 active。
Step 4(可选): 通过 API 创建
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 .
完整一键脚本
#!/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}'
使用方法:
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 负责拉取镜像,如果它没在工作,Snapshot 自然无法推进。
Q: 状态变为 error,错误信息包含 "connection refused"?
A: 镜像地址使用了 localhost:6000,应改为 registry:6000。详情见坑 1。
Q: API 返回 401 Unauthorized?
A: Token 可能已过期。JWT Token 有效期约 24 小时,过期后重新通过 Web 登录获取。
Q: API 返回 403 Forbidden?
A: 改用 JWT Token 而不是 API Key。详情见坑 2。
Q: 如何获取 Organization ID?
A: 调 GET /api/organizations 接口:
curl -s http://localhost:3000/api/organizations \
-H "Authorization: Bearer $JWT" | jq '.[0].id'
Q: Registry 里有哪些镜像?
A: 通过 Registry API 查看:
# 查看所有仓库
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
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
CAD零基础入门教程:坐标输入、图层管理与基础绘图命令
本文面向CAD零基础学习者,系统讲解坐标输入、图层管理与基础绘图命令的核心用法。通过分步实操与常见问题排查,帮助新手建立精确绘图习惯,掌握规范出图的基础能力。
CAD从入门到项目交付:绘图、标注、图块与实战工作流
掌握CAD的核心在于建立“画得准、标得清、复用快、交付稳”的工作流。本文提供从环境设置、高频命令组合、标注规范、图块标准化到项目分阶段交付的完整路径,帮助初学者避免常见返工陷阱,独立完成可检查、可复用、可打印的工程图纸。
Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤
本文详细解析 Claude Code 登录前的账号类型区分方法,涵盖个人订阅、Teams 席位与企业 Enterprise 席位的授权路径差异。提供终端登录命令、环境变量排查及常见异常处理步骤,帮助用户快速完成正确授权并避免登录路径混淆。
Claude Code 文件修改前的权限模式配置与命令审批指南
本文详细介绍Claude Code在修改文件前的权限模式配置方法,包括defaultMode可选值、permissions allow与deny规则设置、多层级配置文件管理以及 status验证技巧,帮助开发者安全高效地使用AI编程助手。
Claude Code接入VS Code后先测扩展和终端命令
在VS Code中接入Claude Code后,建议优先验证扩展面板与集成终端两条入口。本文提供标准检查顺序、关键命令与常见故障排查路径,帮助你快速确认环境就绪,避免后续开发受阻。
- 热门数据榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-09-01 16:53
2026-09-01 16:52
2026-09-01 14:27
2026-09-01 14:12
2026-09-01 14:10
2026-09-01 14:07
2026-09-01 13:55
2026-09-01 13:47
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

