Community图像github.com

thanatornPik/nextjs-skill-app-workshop

安全地构建并本地运行 Next.js 应用的 Docker 生产镜像。当用户想要构建 Docker 镜像、使用环境变量文件运行容器、检查镜像版本是否已存在本地,或在不硬编码项目名的情况下本地部署 Next.js 应用时,请使用此技能。

nextjs-skill-app-workshop 是什么?

该技能面向开发者与 AI 代理(如 Claude Code、Cursor、Codex),提供一套标准化、安全的流程,用于在本地通过 Docker 构建和运行 Next.js 应用的生产镜像。它自动从 package.json 或当前目录名推断项目名称,并将其规范化为合法的 Docker 镜像名,从而避免硬编码。技能会执行全面的安全检查:验证工作目录、确认 Dockerfile 和环境变量文件存在、检查 Docker 守护进程状态,并在构建前检查镜像标签是否已存在本地,避免不必要的重建。运行容器前,还会检查容器名是否已被占用,并提示用户确认。最终输出详细的验证结果,包括容器状态、端口映射和 HTTP 响应检查。这一套流程确保了本地开发与生产部署前后的一致性,同时最大限度降低了因镜像标签冲突、端口占用或缺少环境文件而导致部署失败的风险。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/thanatornPik/nextjs-skill-app-workshop/tree/HEAD/.agents/skills/deploy-docker-production

Installed? Explore more 图像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Docker Next.js 本地部署技能

目的

使用此技能通过带有版本号的镜像标签来构建并运行 Next.js 应用程序的 Docker 镜像。

此技能不得硬编码项目名称。除非用户提供了具体名称,否则应从当前仓库推断镜像名称。

项目名称解析

在构建之前,确定以下值:

PROJECT_NAME=<解析后的项目名称>
IMAGE_NAME=<解析后的镜像名称>
IMAGE_VERSION=<解析后的版本>
IMAGE_TAG=${IMAGE_NAME}:${IMAGE_VERSION}
CONTAINER_NAME=<解析后的容器名称>
ENV_FILE=<解析后的环境变量文件>
HOST_PORT=<解析后的主机端口>
CONTAINER_PORT=<解析后的容器端口>

解析规则:

  1. 如果用户提供了镜像名称,则使用该名称。

  2. 否则,读取 package.json 并使用其中的 name 字段。

  3. 如果 package.json 中没有 name,则使用当前文件夹名称。

  4. 规范化镜像名称:

    • 小写
    • 将空格和下划线替换为连字符
    • 移除 Docker 镜像名称中的非法字符
  5. 如果用户提供了版本,则使用该版本。

  6. 否则,默认为 1.0.0。

  7. 如果用户提供了容器名称,则使用该名称。

  8. 否则,使用规范化后的镜像名称作为容器名称。

  9. 如果用户提供了环境变量文件,则使用该文件。

  10. 否则,默认为 .env.production。

  11. 如果用户提供了端口,则使用它们。

  12. 否则,默认 HOST_PORT=4000 和 CONTAINER_PORT=3000。

示例:

package.json 中的名称: nextjs-skill-app-workshop

PROJECT_NAME=nextjs-skill-app-workshop
IMAGE_NAME=nextjs-skill-app-workshop
IMAGE_VERSION=1.0.0
IMAGE_TAG=nextjs-skill-app-workshop:1.0.0
CONTAINER_NAME=nextjs-skill-app-workshop
ENV_FILE=.env.production
HOST_PORT=4000
CONTAINER_PORT=3000

安全规则

在执行任何构建或运行命令之前:

  1. 确认当前工作目录是项目根目录。

  2. 确认 Dockerfile 存在。

  3. 确认环境变量文件存在。

  4. 确认 Docker 已安装并正在运行。

  5. 检查请求的镜像标签是否已存在于本地。

  6. 检查请求的容器名称是否已存在。

  7. 切勿打印环境变量文件中的密钥。

  8. 除非用户明确要求,否则不要使用 latest 标签。

  9. 不要运行破坏性清理命令,例如:

    • docker system prune
    • docker image prune
    • docker volume prune
  10. 未经用户明确确认,不得停止、移除或替换已有的容器。

  11. 除非用户明确确认,否则不要重建已有的版本标签。

预检检查

首先运行这些检查:

pwd
ls -la

test -f package.json && echo "OK: package.json 找到" || echo "WARN: package.json 未找到"
test -f Dockerfile && echo "OK: Dockerfile 找到" || echo "ERROR: Dockerfile 未找到"
test -f "$ENV_FILE" && echo "OK: 环境变量文件找到: $ENV_FILE" || echo "ERROR: 环境变量文件未找到: $ENV_FILE"

docker --version
docker info >/dev/null && echo "OK: Docker 守护进程正在运行" || echo "ERROR: Docker 守护进程未运行"

如果缺少 Dockerfile,停止并报告问题。

如果缺少环境变量文件,停止并报告问题。除非用户要求,否则不要创建占位环境变量文件。

如果 Docker 守护进程未运行,停止并告知用户启动 Docker Desktop 或 Docker Engine。

建议的辅助命令

从 package.json 推断镜像名称:

node -p "require('./package.json').name"

如果 package.json 不存在或没有 name,则使用当前目录名称:

basename "$PWD"

手动规范化项目名称时,使用小写短横线命名法(kebab-case)。

示例:

My Next App -> my-next-app
nextjs_skill_app -> nextjs-skill-app

版本标签检查

在构建之前,检查请求的镜像标签是否已存在:

docker image inspect "$IMAGE_TAG" >/dev/null 2>&1 \
  && echo "EXISTS: $IMAGE_TAG" \
  || echo "AVAILABLE: $IMAGE_TAG"

同时列出此镜像已有的本地版本:

docker images "$IMAGE_NAME" --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}"

如果请求的镜像标签已存在:

  1. 不要运行 docker build。
  2. 报告该版本已存在于本地。
  3. 建议下一个补丁版本,例如 1.0.1。
  4. 询问用户是使用新版本还是明确重建同一标签。

仅当用户明确确认时,才重建现有标签。

容器名称检查

在运行容器之前,检查容器名称是否已存在:

docker ps -a --filter "name=^/${CONTAINER_NAME}$" \
  --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"

如果已存在同名的容器:

  1. 不要使用相同名称运行另一个容器。
  2. 报告已有容器的状态。
  3. 询问用户是停止/移除它还是使用不同的容器名称。
  4. 不要自动移除它。

构建命令

如果镜像标签不存在,运行:

docker build -t "$IMAGE_TAG" .

构建后,验证镜像是否存在:

docker image inspect "$IMAGE_TAG" >/dev/null \
  && echo "OK: 镜像构建成功: $IMAGE_TAG" \
  || echo "ERROR: 构建后未找到镜像: $IMAGE_TAG"

运行命令

如果镜像存在且容器名称可用,运行:

docker run --restart=always -d \
  --name "$CONTAINER_NAME" \
  --env-file "$ENV_FILE" \
  -p "${HOST_PORT}:${CONTAINER_PORT}" \
  "$IMAGE_TAG"

运行后验证

运行容器后,使用以下命令验证:

docker ps --filter "name=^/${CONTAINER_NAME}$" \
  --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"

docker logs --tail=80 "$CONTAINER_NAME"

curl -I "http://localhost:${HOST_PORT}"

预期结果:

  1. 容器状态应为 Up。
  2. 端口映射应包含 ${HOST_PORT}->${CONTAINER_PORT}。
  3. 日志不应显示致命错误。
  4. curl -I 应返回 HTTP 响应,例如 200、301、302、307 或 308。

如果 curl 失败,检查日志并报告可能的原因。

常见故障处理

镜像标签已存在

报告:

镜像标签已存在于本地:
<IMAGE_TAG>

建议操作:
- 使用新的补丁版本,例如 1.0.1
- 或明确确认重建同一标签

容器名称已存在

报告:

容器已存在:
<CONTAINER_NAME>

请确认是否停止/移除它,或提供不同的容器名称。

端口已被占用

检查:

lsof -i :"$HOST_PORT"

报告占用该端口的进程,并询问用户是否要更改 HOST_PORT。

环境变量文件缺失

报告:

未找到环境变量文件:
<ENV_FILE>

在此文件存在之前,我无法使用 --env-file 运行容器。

不要打印或推断密钥。

Docker 守护进程未运行

报告:

Docker 已安装,但守护进程未运行。
请启动 Docker Desktop 或 Docker Engine,然后再次运行预检检查。

最终响应格式

完成后,报告:

结果:
- 项目:<PROJECT_NAME>
- 镜像:<IMAGE_TAG>
- 容器:<CONTAINER_NAME>
- 环境变量文件:<ENV_FILE>
- 端口:http://localhost:<HOST_PORT>
- 重启策略:always
- 验证:通过/失败

使用的命令:
<列出重要命令>

备注:
<任何警告、已有的镜像/容器冲突或后续操作>

如果工作流程因版本标签已存在、环境变量文件缺失、容器已存在、Docker 错误或端口冲突而停止,请明确说明阻塞问题以及最安全的下一步命令。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能