关于 zeabur-template
面向创建、调试和发布 Zeabur 模板的开发者,汇总模板结构、部署迭代及常见配置规则。内容还涵盖 Docker 镜像、端口、域名和内置变量等参考。
主要功能
- 01指导模板创建与发布
- 02提供 YAML 结构和变量参考
- 03介绍部署日志驱动的调试流程
- 04说明 Docker 镜像与服务配置规则
- 05涵盖域名和 TCP 端口配置
适用场景
- 01从现有 Docker 镜像创建模板
- 02排查模板部署故障
- 03配置模板中的数据库与公开域名
- 04检查 TCP 服务的端口转发配置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zeabur/ agent-skills --skill zeabur-template安装后在 Claude Code 中输入/zeabur-template确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/complexity-levels.mddatabase-configs.mdhard-won-lessons.md详细介绍
Zeabur 模板知识库
始终使用
npx zeabur@latest调用 Zeabur CLI。 切勿直接使用zeabur或通过其他安装方式使用。如果无法使用npx,请先安装 Node.js。
本技能提供创建、调试和发布 Zeabur 模板所需的全面知识,结合了参考文档与真实模板开发中经实践验证的模式。
外部文档
如需获取最新架构和详细文档,请从 https://raw.githubusercontent.com/zeabur/zeabur-template-doc/main/ 获取:
| 用户需求 | 要获取的文档 | 路径 |
|---|---|---|
| 从头开始创建模板 | 分步指南 | docs/GUIDE.md |
| 转换 docker-compose.yml | 迁移指南 | docs/DOCKER_COMPOSE_MIGRATION.md |
| 查询 YAML 字段或内置变量 | 技术参考 | docs/REFERENCE.md |
| 命名、设计模式和最佳实践 | 最佳实践 | docs/BEST_PRACTICES.md |
| 调试模板错误 | 故障排除 | docs/TROUBLESHOOTING.md |
| 部署前检查清单 | 检查清单 | docs/CHECKLIST.md |
| 快速查看综合概览 | 综合提示词 | prompt.md |
模板 YAML 架构也可在 https://schema.zeabur.app/template.json 获取,预构建服务架构可在 https://schema.zeabur.app/prebuilt.json 获取。
核心原则
0. 所有服务都必须使用带 Docker 镜像的 PREBUILT_V2
模板中的每项服务都必须设置为 template: PREBUILT_V2,并以 Docker 镜像作为来源。 切勿在模板中使用 template: GIT、ARBITRARY_GIT 或 GITHUB 来源——这些来源不受支持。
如果项目没有已发布的 Docker 镜像(例如发布在 Docker Hub、GHCR 等平台),请告知用户,他们需要先构建并发布 Docker 镜像,然后才能创建模板。不要尝试绕过这一要求。
如果用户要求你构建镜像,请按以下工作流操作:
- 克隆项目仓库并查找其
Dockerfile(通常位于仓库根目录) - 查看
Dockerfile以了解构建阶段——使用生产阶段(通常名为runner或production) - 查看
docker-compose.yml或docker-compose.fullapp.yml,以确定正确的启动命令、环境变量和卷——这是经过实践验证的生产配置 - 构建 amd64 镜像(Zeabur 服务器使用 amd64,本地 Mac 使用 arm64):
docker buildx build --platform linux/amd64 --target runner -t org/image:tag --push . - 推送后,确认 Docker Hub 仓库为公开状态:
组织账号下的新仓库通常默认设为私有。如果curl -s "https://hub.docker.com/v2/repositories/ORG/IMAGE/" | grep is_privateis_private: true,用户必须在 Docker Hub 上将其设为公开。
1. 切勿从头开始
收到创建模板的请求时,务必先查找现有配置:
- 首先检查是否存在 Docker 镜像——搜索 Docker Hub、GHCR(
ghcr.io/org/repo)或项目的 CI/CD,查找已发布的镜像。如果没有,请停止并告知用户。 - 搜索项目的
docker-compose.yml、docker-compose.yaml或compose.yml - 查找 Helm chart(
Chart.yaml、values.yaml) - 检查项目的 GitHub 仓库中是否有部署 YAML 文件
- 以这些文件为基础构建 Zeabur 模板,而非仅将其用作参考——它们包含经过实践验证的环境变量、端口映射、卷挂载和服务依赖关系
2. 根据运行时日志迭代——不要指望一次成功
即使是经验丰富的开发者,也无法一次就创建出可正常运行的模板。工作流是一个迭代循环:
- 编写或更新模板 YAML
- 部署模板
- 很可能会失败——检查运行时日志以找到原因
- 修复模板中的问题
- 删除项目,并从头重新部署
- 重复以上步骤,直到模板实现一键部署成功
这是正常流程,并不意味着失败。不要试图在部署前把所有事情都做到完美——尽早部署、查看日志并持续迭代。
3. 复用现有模板——切勿从头编写常见服务
当模板需要常见服务(PostgreSQL、Redis、MySQL、MongoDB 等)时,不要自行编写服务定义。请改为:
- 搜索已使用该服务的现有模板:
npx zeabur@latest template search postgres - 找到包含所需服务的模板
- 获取模板的原始 YAML,查看确切的服务定义:
npx zeabur@latest template get -c TEMPLATE_CODE --raw - 将服务定义直接从该模板复制到你的模板中
如何判断模板是否可信:
- 许多模板由普通用户创建,可能无法正常运行
- 优先选择部署次数更多的模板——部署次数越多,经过的实战检验越充分
- 优先选择官方模板,而非用户提交的模板——Zeabur 团队会审核官方模板
迭代循环的 CLI 命令
部署模板:
npx zeabur@latest template deploy -f YOUR_TEMPLATE.yaml
用于非交互模式(自动化):
npx zeabur@latest template deploy -i=false \
-f YOUR_TEMPLATE.yaml \
--project-id PROJECT_ID \
--var PUBLIC_DOMAIN=myapp
列出服务(以获取 SERVICE_ID):
npx zeabur@latest service list --project-id PROJECT_ID
检查运行时日志:
npx zeabur@latest deployment log --service-id SERVICE_ID
在运行中的服务内执行命令(类似于 docker exec):
npx zeabur@latest service exec --id SERVICE_ID -- SHELL_COMMAND
这对调试非常有用——可检查文件路径、环境变量、测试连接、查看文件系统等。示例:
npx zeabur@latest service exec --id SERVICE_ID -- ls /app
npx zeabur@latest service exec --id SERVICE_ID -- env | grep DATABASE
npx zeabur@latest service exec --id SERVICE_ID -- nc -z localhost 5432
重启服务(有助于清除 ImagePullBackOff 或强制重新拉取):
npx zeabur@latest service restart --id SERVICE_ID -i=false -y
删除项目并重新开始:
npx zeabur@latest project delete --id PROJECT_ID
危险操作——删除项目之前,必须征得用户的明确确认,并清楚说明 Project ID、Name 和 createdAt 时间戳。未经确认,绝不删除。
发布新模板:
npx zeabur@latest template create -f YOUR_TEMPLATE.yaml
这会返回一个模板 URL,例如 https://zeabur.com/templates/XXXXXX,其中包含模板代码。
更新现有模板:
npx zeabur@latest template update -c TEMPLATE_CODE -f YOUR_TEMPLATE.yaml
快速参考:模板框架
# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
name: ServiceName
spec:
description: |
English description (1-3 sentences)
icon: https://raw.githubusercontent.com/zeabur/service-icons/main/marketplace/service.svg
coverImage: https://example.com/cover.webp
tags:
- Category
variables: []
readme: |
# Service Name
English documentation...
services:
- name: service-name
icon: https://raw.githubusercontent.com/zeabur/service-icons/main/marketplace/service.svg
template: PREBUILT_V2
spec:
source:
image: image:tag
command: # MUST be inside source, alongside image
- /bin/sh
- -c
- /opt/app/startup.sh
ports:
- id: web
port: 8080
type: HTTP
portForwarding:
enabled: true # Auto-expose TCP/UDP ports externally (default: true)
healthCheck: # ensures port is ready before dependents start
type: TCP
port: web # references the port ID above
volumes:
- id: data
dir: /path/to/data
configs:
- path: /opt/app/startup.sh
permission: 493 # 0755
envsubst: false
template: |
#!/bin/sh
exec node server.js
env:
VAR_NAME:
default: value
expose: true
localization:
zh-TW:
description: ...
variables: []
readme: |
# ...
zh-CN:
description: ...
variables: []
readme: |
# ...
ja-JP:
description: ...
variables: []
readme: |
# ...
es-ES:
description: ...
variables: []
readme: |
# ...
id-ID:
description: ...
variables: []
readme: |
# ...
快速参考:内置变量
| 变量 | 用途 |
|---|---|
${PASSWORD} | 自动生成的安全密码 |
${ZEABUR_WEB_URL} | 完整的公开 URL(例如 https://app.zeabur.app) |
${ZEABUR_WEB_DOMAIN} | 仅域名(例如 app.zeabur.app) |
${CONTAINER_HOSTNAME} | 用于服务间通信的内部主机名 |
${[PORTID]_PORT} | 按端口 ID 指定的端口值(例如 ${DATABASE_PORT}) |
${PORT_FORWARDED_HOSTNAME} | 外部主机名,用于端口转发(启用后自动设置,可在环境变量和 instructions 中使用) |
${[PORTID]_PORT_FORWARDED_PORT} | 外部转发端口号(启用后自动设置,可在环境变量和 instructions 中使用) |
ZEABUR_<PORT_ID>_URL 格式:对于名为 web 的端口,对应 ${ZEABUR_WEB_URL};对于 console,对应 ${ZEABUR_CONSOLE_URL}。
快速参考:command 的位置
重要:command 必须放在 source 内,与 image 并列。不得放在 spec 层级。
# WRONG -- command at spec level (will be IGNORED, container uses default CMD)
spec:
source:
image: python:3.12-slim
command:
- /bin/sh
- -c
- /opt/app/start.sh
# CORRECT -- command inside source
spec:
source:
image: python:3.12-slim
command:
- /bin/sh
- -c
- /opt/app/start.sh
注意: 外部文档可能会将
command放在spec层级。这是不正确的。请始终将command放在source内,JSON schema(schema.zeabur.app/prebuilt.json)已确认此做法。
快速参考:YAML 注意事项
# RISKY -- @ at start of value is a YAML reserved indicator (may cause parse errors)
description: @BotFather token
# SAFE -- quote the value or avoid @ at start
description: "Token from @BotFather for Telegram bot"
description: Telegram bot token from BotFather
快速参考:Docker 镜像 ENTRYPOINT
某些基础镜像设置了 ENTRYPOINT,这会与 command 冲突。
| 镜像 | ENTRYPOINT | 问题 |
|---|---|---|
ghcr.io/astral-sh/uv:python3.12-* | uv | command 会变成传给 uv 的参数,容器会显示 uv help 后退出 |
node:* | 无 | 可安全使用 |
python:* | 无 | 可安全使用 |
如果使用的镜像设置了 ENTRYPOINT,请换用普通基础镜像(例如 python:3.12-slim-bookworm)或未设置 ENTRYPOINT 的镜像。
快速参考:TCP 服务(代理、数据库、游戏服务器等)
非 Web 应用的服务——例如 HTTP 代理(Tinyproxy、Squid)、数据库、游戏服务器、VPN 服务器,或客户端通过 TCP/UDP 直接连接的任何服务——不得使用 HTTP 端口类型或 domainKey。请改为:
- 使用
type: TCP(或UDP)——这样可防止 Zeabur 的反向代理(Ingress)拦截流量 - 设置
portForwarding: enabled: true——自动将端口暴露到外部,以便客户端直接连接 - 不要使用
domainKey——TCP 服务不需要域名;用户通过转发的主机名和端口连接
# CORRECT -- TCP service (e.g. HTTP proxy, database, game server)
spec:
source:
image: some/tcp-service:latest
ports:
- id: proxy
port: 8888
type: TCP # NOT HTTP — clients connect directly
portForwarding:
enabled: true # Auto-expose this port externally
env:
# ...
# WRONG -- using HTTP type for a TCP proxy
spec:
ports:
- id: proxy
port: 8888
type: HTTP # Zeabur's Ingress will intercept CONNECT requests
# Missing portForwarding — users must manually enable in Dashboard
为什么不能使用 HTTP? Zeabur 的 HTTP 端口类型会通过反向代理(Ingress/Envoy)路由流量,由该代理终止 TLS 并执行基于 Host 的路由。这会导致 HTTP CONNECT(代理使用的协议)、原始 TCP 数据流(数据库使用)和自定义二进制协议(游戏服务器使用)等协议无法正常工作。
端口转发变量(用于 instructions 或 readme):
${PORT_FORWARDED_HOSTNAME}— 外部主机名${PROXY_PORT_FORWARDED_PORT}— 外部端口(格式:${[PORTID]_PORT_FORWARDED_PORT})
TCP 服务部署后的测试:
部署 TCP 服务后,请验证端口转发是否正常工作:
-
首先检查内部连接(在容器内):
npx zeabur@latest service exec --id SERVICE_ID -- curl -x http://127.0.0.1:8888 https://ifconfig.co -
从 Dashboard 的 Networking 标签页获取转发的主机名和端口,或使用:
npx zeabur@latest service network --id SERVICE_ID -
测试外部连接:
curl -x http://FORWARDED_HOST:FORWARDED_PORT https://ifconfig.co
如果端口转发显示为 DISABLED,请启用它:
npx zeabur@latest service port-forward --id SERVICE_ID --enable
快速参考:无头服务(无 HTTP)
如果服务没有监听任何 HTTP 端口(502 Bad Gateway),请参阅 zeabur-port-mismatch 技能了解修复方法。
快速参考:关键规则
# WRONG -- using :latest tag (may serve cached/stale image)
image: rajnandan1/kener:latest
# CORRECT -- pin to specific version
image: rajnandan1/kener:4.0.16
# WRONG -- hardcoded password
POSTGRES_PASSWORD:
default: mypassword123
# CORRECT -- use ${PASSWORD}
POSTGRES_PASSWORD:
default: ${PASSWORD}
expose: true
# WRONG -- PUBLIC_DOMAIN gives incomplete URL
APP_URL:
default: https://${PUBLIC_DOMAIN}
# CORRECT -- ZEABUR_WEB_URL gives full URL
APP_URL:
default: ${ZEABUR_WEB_URL}
readonly: true
# WRONG -- other services can't reference without expose
POSTGRES_HOST:
default: ${CONTAINER_HOSTNAME}
# CORRECT -- expose + readonly for connection info
POSTGRES_HOST:
default: ${CONTAINER_HOSTNAME}
expose: true
readonly: true
# WRONG -- referencing variables without declaring dependency
- name: app
spec:
env:
DB: ${POSTGRES_HOST}
# CORRECT -- declare dependency first
- name: app
dependencies:
- postgresql
spec:
env:
DB: ${POSTGRES_HOST}
# WRONG -- HTTP type for a TCP proxy/database/game server
ports:
- id: proxy
port: 8888
type: HTTP
# CORRECT -- TCP type + portForwarding for non-web services
ports:
- id: proxy
port: 8888
type: TCP
portForwarding:
enabled: true
域名绑定
在需要公共域名的服务上使用 domainKey。它对应于 spec.variables 中定义的 type: DOMAIN 变量。
单个域名:
domainKey: PUBLIC_DOMAIN
多个域名(不同端口):
domainKey:
- port: web
variable: ENDPOINT_DOMAIN
- port: console
variable: ADMIN_ENDPOINT_DOMAIN
常见数据库配置
请参阅 references/database-configs.md,查看可直接复制粘贴的 PostgreSQL、MySQL/MariaDB、Redis 配置以及标准卷路径。
模板复杂度级别
请参阅 references/complexity-levels.md,了解 5 级复杂度指南(从单个服务到大型多服务平台)。
编写 name、description、readme、icon 和 coverImage
信息来源(按优先级排序):
- 项目的 GitHub 仓库 README
- 项目的官方网站
- 其他公开来源(博客文章、文档网站等)
关键规则:
- 不要直接复制粘贴原始 README。 请撰写关于该项目的 Zeabur 模板的介绍,而不是介绍项目本身。readme 应:
- 简要介绍项目是什么
- 重点说明如何使用此模板(部署步骤、配置、域名绑定)
- 包含与 Zeabur 部署相关的重要注意事项和故障排除技巧
- 始终注明许可证和出处。 如果原项目采用 MIT、Apache 或其他许可证:
- 在 readme 中注明许可证
- 链接到原始仓库
- 如果有官方网站,也要添加链接
- 这是法律要求——绝不可省略
- icon 和 coverImage:从项目的 GitHub 仓库或官方网站查找其 Logo。使用指向图片(SVG、PNG 或 WebP)的直接 URL。务必确认 URL 返回 HTTP 200:
常见问题:curl -s -o /dev/null -w "%{http_code}" "URL"raw.githubusercontent.comURL 中的分支名称错误(develop、main或master)。
本地化要求
必须提供 6 种语言:en-US(位于 spec 中)、zh-TW、zh-CN、ja-JP、es-ES、id-ID。
需要翻译: description、variables[].name、variables[].description、readme
不要翻译: key、type、${VARIABLE_NAMES}、URL
经验教训
请参阅 references/hard-won-lessons.md,了解经过实践验证的模式:wait-for-db、首次运行初始化标记、OOM 恢复、ImagePullBackOff 等。