关于 dockerize
dockerize 是一项 Agent 技能,用于创建适配 haloy 部署单个服务的 Dockerfile。它会检查项目配置和运行需求,并处理构建阶段、健康检查及部署配置指引。
主要功能
- 01识别项目类型与包管理器
- 02检查构建和运行需求
- 03生成优化的多阶段 Dockerfile
- 04检查健康检查端点
- 05提供 haloy 配置指引
适用场景
- 01为 haloy 部署单个应用构建容器
- 02添加包含健康检查的 Dockerfile
- 03根据项目文件确定运行时版本
- 04准备 Docker 构建与本地测试说明
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ haloydev/ agent-skills --skill dockerize安装后在 Claude Code 中输入/dockerize确认已加载。
附带文件references/base-images.mdreferences/tanstack-start.md
详细介绍
为 Haloy 容器化
创建适用于使用 haloy 部署、已针对生产环境优化的 Dockerfile。
如果用户的请求涉及 docker-compose、多个容器或复杂的编排,请告知他们:
“此技能会创建用于 haloy 部署的单个 Dockerfile。Haloy 的工作方式类似于 docker-compose,但面向生产环境,并通过自身的配置处理编排。如果你需要多个服务,每个服务都应有自己的 Dockerfile,并在
haloy.yaml中定义为单独的服务。你希望我改为针对某个特定服务创建 Dockerfile 吗?”
工作原理
-
检测项目类型,检查以下内容:
package.json中是否包含@tanstack/react-start(TanStack Start)package.json中是否包含next(Next.js)package.json(Node.js/JavaScript/TypeScript)bun.lockb、pnpm-lock.yaml、package-lock.json或yarn.lock(Node 包管理器)requirements.txt、pyproject.toml、Pipfile(Python)uv.lock、poetry.lock或pyproject.toml中的[tool.poetry](Python 包管理器)go.mod(Go)Cargo.toml(Rust)Gemfile(Ruby)pom.xml、build.gradle(Java)composer.json(PHP)- 其他指示信息
-
分析应用,确定:
- 构建流程和依赖项
- 运行时要求
- 入口点/启动命令
- 必需的环境变量
- 静态资源或构建产物
-
检查健康检查端点;如果缺失,询问用户是否需要创建(见下方“健康检查”部分)
-
创建经过优化的 Dockerfile,遵循最佳实践:
- 使用多阶段构建来减小镜像体积
- 选择合适的基础镜像(尽可能使用 Alpine)
- 合理安排层顺序以提高缓存效率
- 使用非 root 用户以提升安全性
- 使用指向健康检查端点的 HEALTHCHECK 指令
-
如果不存在
haloy.yaml,提供 haloy 配置指导
健康检查端点
强烈建议所有 haloy 部署都提供 /health 端点。创建 Dockerfile 前,请检查应用是否已有健康检查端点。
健康检查的重要性
Haloy 使用健康检查来:
- 实现零停机部署:新容器必须通过健康检查后才能接收流量
- 自动恢复:不健康的容器会自动重启
- 验证部署:如果应用无法正常启动,部署会快速失败
如果没有健康检查,haloy 就无法确认应用是否正常运行,这可能导致流量被路由到故障容器。
检查现有健康检查端点
搜索现有健康检查端点:
/health、/healthz、/api/health、/_health- 查找返回状态码 200 或
{ status: "ok" }的路由定义
询问用户
如果不存在健康检查端点,请询问用户:
“你的应用似乎没有健康检查端点。Haloy 使用健康检查来实现零停机部署和自动恢复。你希望我创建一个
/health端点吗?”
如果用户同意,请为对应框架创建一个最精简的健康检查端点:
TanStack Start(src/routes/health.tsx):
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/health")({
server: {
handlers: {
GET: async () => {
return Response.json({ status: "ok" });
},
},
},
});
Express/Node.js:
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
Next.js(app/health/route.ts 或 pages/api/health.ts):
export async function GET() {
return Response.json({ status: 'ok' });
}
FastAPI:
@app.get("/health")
def health():
return {"status": "ok"}
Go(net/http):
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"ok"}`))
})
健康检查最佳实践
- 快速返回(基本健康检查中避免查询数据库)
- 健康时返回 HTTP 200,不健康时返回非 200 状态码
- 响应内容保持精简:
{"status": "ok"}即可 - 使用统一路径:惯例是
/health
决策流程
除非缺少关键值,否则使用默认值。仅在必要时询问用户。
- 健康检查端点:仅当找不到现有健康检查路由时才询问。
- 启动命令:使用现有的
scripts.start或框架默认值。如果没有明确的入口点,则询问。 - 端口:使用常见默认值(Node 为 3000,Python 为 8000),除非配置文件或环境变量指定了端口。
- 包管理器:根据锁文件推断。如果不存在锁文件,Node 默认使用 npm,Python 默认使用 pip。
基础镜像版本
重要:始终检测本地运行时版本,以确保开发和生产环境一致。不要依赖训练数据中的版本号。
版本选择优先级:
- 项目配置文件(优先级最高)——
.nvmrc、.node-version、engines.node、.python-version、go.mod、rust-toolchain.toml、.ruby-version等。 - 本地安装的版本——运行相应运行时的版本命令
- 回退到
references/base-images.md——仅在以上方法都失败时使用
请参阅 references/base-images.md,了解完整的版本检测指南、配置文件位置、版本到标签的映射,以及当前建议的回退版本。
默认使用 slim 变体;需要更小的镜像时使用 alpine(但可能存在兼容性取舍)。始终使用具体的主次版本标签,绝不使用 latest。
Dockerfile 最佳实践
通用原则
- 使用具体的版本标签,而不是
latest(参见上文“基础镜像版本”) - 合并 RUN 命令以尽量减少镜像层
- 按照指令变更频率从低到高排序
- 使用
.dockerignore排除不必要的文件 - 在生产环境中以非 root 用户运行
- 添加 EXPOSE 以供文档说明
多阶段构建模式
# Build stage (verify current LTS version in references/base-images.md)
FROM node:24-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN npm run build
# Production stage
FROM node:24-slim AS runner
WORKDIR /app
RUN addgroup -g 1001 -S appgroup && adduser -u 1001 -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]
框架特定注意事项
TanStack Start:详细说明请参阅 references/tanstack-start.md。要点:
- package.json 中需要
"type": "module" - 需要包含
tanstackStart()和nitro()插件的vite.config.ts - 构建输出位于
.output/server/index.mjs - 使用 Node 24 slim,并通过 corepack 使用 pnpm
- 添加
/health路由用于健康检查
Next.js:使用 standalone 输出模式,复制 .next/standalone 和 .next/static
Vite/React:构建静态文件,并使用 nginx 或 Node 服务提供
Python/FastAPI:使用 slim 镜像,通过 --no-cache-dir 安装
Go:构建静态二进制文件,使用 scratch 或 distroless 镜像来精简镜像
输出格式
创建 Dockerfile 后,按以下顺序提供输出:
- 完整的 Dockerfile
- 如果不存在
.dockerignore文件,则提供一个 - 在本地构建和测试的说明:
docker build -t myapp . docker run -p 3000:3000 myapp - 如果不存在
haloy.yaml,请告知用户:"要完成 haloy 设置,你需要一个
haloy.yaml配置文件。你可以运行/haloy-config技能来生成该文件,也可以查看 haloy 文档了解配置选项。"
参考文件
阅读相应的参考文件以了解详细说明:
- 基础镜像:
references/base-images.md——所有运行时当前建议的版本(请先查看此文件!) - TanStack Start:
references/tanstack-start.md——完整指南,包含健康检查、数据库设置和 haloy.yaml 示例
何时创建 .dockerignore
始终检查是否已有 .dockerignore。如果没有,请根据项目类型创建一个。常见的排除项:
node_modules
.git
.env
.env.*
*.log
dist
.next
.output
.vinxi
__pycache__
*.pyc
.venv
target
haloy.yaml
重要:始终将 haloy.yaml 添加到 .dockerignore 中。haloy 使用此文件进行部署配置,但容器内不需要它。排除该文件可改善 Docker 层缓存,因为对 haloy.yaml 的更改(例如更新域名或环境变量)不会使构建缓存失效。