Communitygithub.com

Nuvraxis/nuvraxis-plugins

适用于 Next.js 独立应用在 pnpm + Turborepo 单体仓库中的 Dockerfile 规则——多阶段构建(turbo prune → pnpm fetch/offline install → turbo build → 最小运行镜像),固定使用基于摘要的 Node 26 Alpine 镜像,通过校验和验证 pnpm 二进制文件,使用非 root 用户 uid 1001,只读根文件系统并挂载可写的 .next/cache,通过 /api/health 进行健康检查,仅允许 NEXT_PUBLIC_* 值的构建参数,支持 BuildKit 密钥和缓存挂载、多架构、OCI 标签及 .dockerignore。当仓库包含 Dockerfile、.dockerignore、compose 文件或 next.config 中配置了 output: 'standalone',或者需要容器化、缩减、加固或调试镜像时使用。

nuvraxis-plugins 是什么?

该技能为 Next.js 独立应用在基于 pnpm 和 Turborepo 的单体仓库中提供一套严格的 Dockerfile 多阶段构建规则。它定义了五个构建阶段(base、pruner、deps、builder、runner),通过 turbo prune 筛选出目标应用及其工作空间依赖,然后利用 pnpm fetch 和离线安装优化层缓存,使源代码修改仅触发最后两个阶段的重建,大幅提升 CI/CD 构建效率。技能要求精确固定 Node 版本(使用 Alpine 镜像的完整摘要)和 pnpm 版本(从 GitHub release 下载并通过 SHA-256 校验,禁止 npm -g pnpm 或 Corepack),并支持 amd64/arm64 双架构构建。最终运行镜像仅包含独立输出目录中的 .next/standalone、.next/static 和 public 目录,以非 root 用户 uid/gid 1001 运行,只读根文件系统且仅允许 .next/cache 写入,并设置 HEALTHCHECK 用于 Docker 和 Compose 环境(Kubernetes 使用自己的探针)。该技能广泛适用于 Claude Code、Cursor 等 AI 编程助手,其规则涵盖了环境变量处理(仅 NEXT_PUBLIC_* 作为构建参数)、BuildKit 密钥挂载(防止密钥留在镜像历史中)、pnpm store 缓存挂载、OCI 标签管理以及 .dockerignore 建议,确保构建出的镜像安全、高效、可复现且符合容器最佳实践。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Nuvraxis/nuvraxis-plugins/tree/HEAD/plugins/nuvraxis-frontend/skills/docker-nextjs

在你喜欢的 AI 中提问

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

文档

针对 Next.js 的 Docker 配置

用于应用镜像。Next.js 独立部署相关细节在 nextjs-production(references/self-hosting.md);在 Kubernetes 中运行该镜像的内容在 helm-nextjs;CI 如何构建并推送该镜像的内容在 github-actions。

模板的 apps/<app>/Dockerfile 是事实来源;references/Dockerfile.md 包含完整内容及注释。从仓库根目录构建:docker build -f apps/<app>/Dockerfile -t <app> .

规则

  1. 五个阶段:base → pruner → deps → builder → runner。

    • base:仅包含 Node + pnpm,无其他内容。
    • pruner:在完整仓库上运行 turbo prune <app> --docker,仅保留该应用及其工作空间依赖。
    • deps:仅复制 out/json/(清单文件)和 out/pnpm-lock.yaml,然后执行 pnpm fetch + pnpm install --frozen-lockfile --offline。该层在清单文件或锁文件变更前会被重用,因此源代码编辑不会触发重新安装。
    • builder:复制 out/full/(源代码),执行 pnpm exec turbo run build --filter=<app>。
    • runner:一个全新的 Node 镜像,仅包含独立部署输出。 原因:源代码变更仅重建最后两个阶段,且 runner 无 pnpm、无源代码、无开发依赖。
  2. 通过精确版本和摘要固定 Node 镜像,使其与 .node-version 匹配。 在 ARG NODE_IMAGE 中使用 node:26.12.0-alpine3.24@sha256:6f08…,并在 base 和 runner 阶段使用。摘要是多架构索引,因此 amd64 和 arm64 均可解析。 为何选择 Alpine 而非 distroless:distroless Node 仅发布浮动标签(latest、nonroot),无法精确匹配 .node-version 中的 Node 版本,且没有用于 HEALTHCHECK 的 wget。Alpine 体积小,可精确固定版本,并且 sharp 提供预编译的 musl 二进制文件,因此无需额外软件包即可进行镜像优化。

  3. 从 GitHub 发布二进制文件安装 pnpm,并通过 SHA-256 校验。绝不使用 npm i -g pnpm、Corepack 或未经校验的 curl | sh。 一个 ARG PNPM_VERSION 等于 packageManager,加上每个架构的校验和,用于 pnpm-linux-{x64,arm64}-musl.tar.gz,通过 TARGETARCH 选择。要升级时:更改这三个 ARG,从发布的资产摘要中获取 sha256 值(gh release view v<version> --repo pnpm/pnpm --json assets),并在同一提交中升级 packageManager。如果发布格式发生变化,备用方案:将 pruner/deps/builder 阶段基于 ghcr.io/pnpm/pnpm:<version>(无 Node,需添加),而不是发明新的安装方法。

  4. runner 阶段仅复制三样内容。

    COPY --from=builder /repo/apps/<app>/.next/standalone ./
    COPY --from=builder /repo/apps/<app>/.next/static ./apps/<app>/.next/static
    COPY --from=builder /repo/apps/<app>/public ./apps/<app>/public
    

    独立部署不包含 static 或 public;缺少它们应用将无法提供 CSS 或 JS。在 monorepo 中,服务器位于 apps/<app>/server.js。使用 CMD ["node", "apps/<app>/server.js"],exec 格式,以便 Node 直接接收 SIGTERM。

  5. 以 uid/gid 1001 运行,文件属主为 root。 创建 nextjs:nodejs(1001:1001),保留复制的文件为 root 所有(应用可以读取但无法修改自身代码),仅对 apps/<app>/.next/cache 执行 chown。使用 USER 1001:1001(数字形式),以便 Kubernetes 无需解析名称即可验证 runAsNonRoot。

  6. 镜必须能在只读根文件系统下工作。 唯一的运行时写入路径是 .next/cache(图像优化、ISR/获取缓存)。Kubernetes 在该路径挂载 emptyDir;在本地使用 --tmpfs。测试方式:

    docker run --rm -p 3000:3000 --read-only \
      --tmpfs /app/apps/<app>/.next/cache:uid=1001,gid=1001 \
      --cap-drop ALL --security-opt no-new-privileges <app>
    
  7. 在 runner 阶段设置 NODE_ENV=production、HOSTNAME=0.0.0.0、PORT=3000、NEXT_TELEMETRY_DISABLED=1。 若未设置 HOSTNAME=0.0.0.0,独立服务器将绑定到容器主机名,导致探测失败。

  8. HEALTHCHECK 使用 busybox 的 wget 访问 /api/health。 适用于 docker run/Compose;Kubernetes 会忽略该设置,并使用 chart 中同一路径的探针。

  9. 构建参数仅用于构建时内联的值:NEXT_PUBLIC_* 和 NEXT_DEPLOYMENT_ID。 NEXT_PUBLIC_* 会被编译到 JS 中,因此必须在 builder 阶段作为 ARG + ENV 存在,并且在镜像运行的每个环境中都是相同的。每个环境特有的内容通过 chart 中的运行时环境变量提供。如需添加一个:

    ARG NEXT_PUBLIC_APP_NAME
    ENV NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME}
    

    …同时在两个工作流中添加 build-args,并且 NEXT_PUBLIC_* 已存在于 turbo 的 env 中。

  10. 机密信息绝不应出现在 ARG、ENV 或 COPY 中。 它们会留在镜像历史中。应使用 BuildKit 机密挂载,该挂载仅在该 RUN 命令期间存在:

    RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN pnpm fetch   # 私有注册表
    

    模板的构建步骤已通过这种方式声明了可选的 next_server_actions_key 机密。

  11. 通过 BuildKit 缓存挂载缓存 pnpm 存储。 在 fetch/install/dlx 命令中使用 --mount=type=cache,id=pnpm-store,target=/pnpm/store,并设置 pnpm_config_store_dir=/pnpm/store。存储在同一构建器上的不同构建之间保留,而不会进入镜像层。在 CI 中,层缓存使用 type=gha(参见 github-actions)。

  12. 仓库根目录的 .dockerignore 保持上下文小巧且不包含机密信息。 排除了 node_modules、.next、.turbo、dist、coverage、.env*、.git、.github、charts。包含 Windows 或 macOS 的 node_modules 的上下文会破坏 Linux 镜像中的原生包。

  13. 多架构构建为 linux/amd64,linux/arm64,由 CI 完成。 在本地,构建你自己的架构。除 pnpm 下载外(它通过 TARGETARCH 选择校验和),每个阶段均与架构无关。

  14. 标签: Dockerfile 设置了 org.opencontainers.image.title 和 licenses;CI 通过 docker/metadata-action 添加 source、revision、version、created。不要硬编码版本标签。

  15. 保持各阶段无应用特定的 hack。 不在 runner 中执行 apk add(应用不需要 shell 工具集),不包含 npm,不从主机复制 node_modules。如果应用在运行时需要原生工具,请在注释中说明理由。

调试

症状原因
构建期间出现 extends: … doesn't resolve应用所需的根级别文件不在修剪后的树中:将其移入工作空间包
deps 阶段出现 ERR_PNPM_OUTDATED_LOCKFILE清单文件变更后未提交锁文件
ERR_PNPM_IGNORED_BUILDS新依赖需要安装脚本:在 allowBuilds 中决定
应用启动,但无 CSS/JS未将 .next/static 或 public 复制到 apps/<app>/
健康检查失败,但日志正常HOSTNAME 不是 0.0.0.0
运行时出现 EROFS某些内容在 .next/cache 之外写入;找出它,不要放弃 --read-only
NEXT_PUBLIC_X 为空未作为构建参数传递(它在构建时被烘焙)

验证

docker build -f apps/<app>/Dockerfile -t <app>:local --build-arg NEXT_DEPLOYMENT_ID=local .
docker run -d --name <app> -p 3000:3000 --read-only --tmpfs /app/apps/<app>/.next/cache:uid=1001,gid=1001 --cap-drop ALL <app>:local
curl -fsS localhost:3000/api/health
docker exec <app> id                     # uid=1001(nextjs)
docker inspect --format '{{.State.Health.Status}}' <app>   # 大约 30 秒后变为 healthy
docker rm -f <app>

来源

Individual skills in this repo

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

Nuvraxis/nuvraxis-plugins

>- Biome 2.5 setup and rules for Nuvraxis monorepos — root biome.json with pinned $schema, VCS ignore, formatter settings, the recommended preset with a11y and the react/next domains, nursery policy, organize imports, overrides, nested per-package configs ("extends": "//"), biome check --write locally, biome ci in CI, VS Code settings, and migrating from ESLint/Prettier. Use when the repo has biome.json or biome.jsonc, @biomejs/biome in package.json, .eslintrc*/eslint.config.*/.prettierrc* to migrate, or when fixing lint and formatting errors.

Nuvraxis/nuvraxis-plugins

>- GitHub Actions conventions for Nuvraxis Next.js apps — exactly three workflows: pr.yaml (every PR to any branch: Biome, stylelint, typecheck/test/build with turbo --affected, Docker build + health check, helm lint + kubeconform; publishes nothing), main.yaml (push to main: one multi-arch image to GHCR tagged sha-SHORTSHA and main, provenance + SBOM, gha cache), release.yaml (tag vX.Y.Z: verify on main, retag the existing image without rebuilding, package and push the Helm chart to OCI, GitHub Release with chart, digest and SBOM). Minimal permissions per job, GITHUB_TOKEN only, pinned action majors. Use when editing .github/workflows/*, adding a CI step, or debugging a failed run or release.

Nuvraxis/nuvraxis-plugins

>- Helm chart rules for Nuvraxis Next.js apps — one chart per app in charts/ (named after the app), published to oci://ghcr.io/nuvraxis/charts and synced by Argo CD; Chart.yaml version/appVersion set only by release.yaml; Deployment with startup/liveness/readiness probes on /api/health, non-root read-only security context, emptyDir for .next/cache, ConfigMap + existing Secret via envFrom, Service, Ingress with cert-manager, HPA, PDB, ServiceAccount, topology spread; no Helm hooks; helm lint --strict + kubeconform. Use when the repo has charts/, Chart.yaml, values*.yaml, templates/*.yaml with Helm syntax, or an Argo CD Application, or when asked to deploy, scale, expose or configure the app on Kubernetes.

Nuvraxis/nuvraxis-plugins

>- Production rules for Next.js 16 App Router apps at Nuvraxis — Server/Client Component boundaries, Cache Components ("use cache", cacheLife, cacheTag, updateTag), Server Actions, route handlers, env handling, instrumentation, output standalone and the /api/health route. Use when the project has "next" in package.json, an app/ or src/app/ directory, next.config.ts, proxy.ts, instrumentation.ts, or files named page.tsx, layout.tsx, route.ts, loading.tsx, error.tsx.

相关技能