Communitygithub.com

Nuvraxis/nuvraxis-plugins

Regras Dockerfile para aplicativos Next.js standalone em um monorepo pnpm + Turborepo — construção multi-estágio (turbo prune → pnpm fetch/install offline → turbo build → runner mínimo), Node 26 Alpine fixado por digest, binário pnpm verificado por checksum, usuário não-root uid 1001, sistema de arquivos raiz somente leitura com cache .next gravável, HEALTHCHECK em /api/health, argumentos de build apenas para valores NEXT_PUBLIC_*, segredos BuildKit e montagens de cache, multi-arquitetura, rótulos OCI e .dockerignore. Use quando o repositório tiver um Dockerfile, .dockerignore, arquivo compose ou next.config com output "standalone", ou quando for solicitado a containerizar, reduzir, endurecer ou depurar uma imagem.

O que é nuvraxis-plugins?

Este skill fornece regras e um modelo completo de Dockerfile para construir imagens Docker otimizadas para aplicativos Next.js em modo standalone dentro de um monorepo gerenciado por pnpm e Turborepo. Ele é projetado para maximizar o cache do Docker, reduzir o tamanho da imagem e melhorar a segurança, seguindo práticas recomendadas de construção multi-estágio. O skill detalha cinco estágios (base, pruner, deps, builder, runner) que isolam dependências, fontes e o artefato final, garantindo que apenas o código necessário para a execução esteja na imagem. Além disso, ele enfatiza a importância de fixar a imagem Node por digest, instalar pnpm de forma verificada, executar como usuário não-root, suportar sistemas de arquivos somente leitura e usar HEALTHCHECK para monitoramento. As regras são compatíveis com plataformas como Docker, Docker Compose, Kubernetes e CI/CD (GitHub Actions), e incluem diretrizes para multi-arquitetura, segredos BuildKit, montagens de cache e rótulos OCI. O skill é útil para desenvolvedores que trabalham com Next.js em monorepos e precisam de um processo de containerização consistente, seguro e eficiente.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Docker para Next.js

Use para a imagem do aplicativo. Os fatos standalone do Next.js estão em nextjs-production (references/self-hosting.md); o que executa a imagem no Kubernetes é helm-nextjs; como o CI constrói e envia a imagem é github-actions.

O modelo apps/<app>/Dockerfile é a fonte da verdade; references/Dockerfile.md o contém por completo com notas. Construa a partir da raiz do repositório: docker build -f apps/<app>/Dockerfile -t <app> .

Regras

  1. Cinco estágios: base → pruner → deps → builder → runner.

    • base: Node + pnpm, nada mais.
    • pruner: turbo prune <app> --docker no repositório completo, deixando apenas o aplicativo e suas dependências do workspace.
    • deps: copiar apenas out/json/ (manifestos) e out/pnpm-lock.yaml, então pnpm fetch + pnpm install --frozen-lockfile --offline. Esta camada é reutilizada até que um manifesto ou o arquivo de lock mude, portanto uma edição de código fonte não reinstala.
    • builder: copiar out/full/ (códigos fonte), pnpm exec turbo run build --filter=<app>.
    • runner: uma imagem Node nova com apenas a saída standalone. Por quê: mudanças no código fonte recompilam apenas os dois últimos estágios, e o runner não tem pnpm, códigos fonte ou dependências de desenvolvimento.
  2. Fixar a imagem Node por versão exata e digest, correspondendo ao .node-version. node:26.12.0-alpine3.24@sha256:6f08… em um ARG NODE_IMAGE, usado tanto por base quanto por runner. O digest é o índice multi-arquitetura, então tanto amd64 quanto arm64 resolvem. Por que Alpine em vez de distroless: distroless Node publica apenas tags flutuantes (latest, nonroot), então a versão exata do Node não pode ser correspondida ao .node-version, e não tem wget para o HEALTHCHECK. Alpine é pequeno, fixa exatamente, e sharp fornece binários musl pré-construídos, então a otimização de imagem funciona sem pacotes extras.

  3. Instalar pnpm a partir do binário da release do GitHub, verificado por SHA-256. Nunca npm i -g pnpm, nunca Corepack, nunca um curl | sh não verificado. Um ARG PNPM_VERSION igual a packageManager, mais um checksum por arquitetura para pnpm-linux-{x64,arm64}-musl.tar.gz, selecionado por TARGETARCH. Para atualizar: alterar os três ARGs, obtendo os valores sha256 dos digests de assets da release (gh release view v<version> --repo pnpm/pnpm --json assets), e atualizar packageManager no mesmo commit. Fallback se o formato da release mudar: basear os estágios pruner/deps/builder em ghcr.io/pnpm/pnpm:<version> (sem Node, adicione-o) em vez de inventar um novo método de instalação.

  4. O runner copia exatamente três coisas.

    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
    

    Standalone não inclui static ou public; sem eles o aplicativo não serve JS ou CSS. No monorepo o servidor é apps/<app>/server.js. CMD ["node", "apps/<app>/server.js"], formato exec, então o Node recebe SIGTERM diretamente.

  5. Executar como uid/gid 1001 com arquivos pertencentes a root. Criar nextjs:nodejs (1001:1001), deixar os arquivos copiados como propriedade de root (o aplicativo pode ler mas não alterar seu próprio código), e chown apenas apps/<app>/.next/cache. USER 1001:1001, numérico, para que o Kubernetes possa verificar runAsNonRoot sem resolver nomes.

  6. A imagem deve funcionar com um sistema de arquivos raiz somente leitura. As únicas gravações em tempo de execução vão para .next/cache (otimização de imagem, cache ISR/fetch). O Kubernetes monta um emptyDir lá; localmente use --tmpfs. Teste:

    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. Definir NODE_ENV=production, HOSTNAME=0.0.0.0, PORT=3000, NEXT_TELEMETRY_DISABLED=1 no runner. Sem HOSTNAME=0.0.0.0 o servidor standalone vincula ao hostname do container e as sondagens falham.

  8. HEALTHCHECK acessa /api/health com wget do busybox. É para docker run/Compose; o Kubernetes ignora e usa as sondagens do chart no mesmo caminho.

  9. Argumentos de build são apenas para valores embutidos na construção: NEXT_PUBLIC_* e NEXT_DEPLOYMENT_ID. NEXT_PUBLIC_* é compilado no JS, portanto deve ser um ARG + ENV no builder, e é idêntico em todo ambiente em que a imagem executa. Tudo que é por ambiente é uma variável de ambiente em tempo de execução do chart. Para adicionar um:

    ARG NEXT_PUBLIC_APP_NAME
    ENV NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME}
    

    …mais build-args em ambos os workflows e NEXT_PUBLIC_* já está no env do turbo.

  10. Segredos nunca vão em um ARG, ENV ou COPY. Eles ficariam no histórico da imagem. Use uma montagem de segredo BuildKit, que existe apenas para aquele RUN:

    RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN pnpm fetch   # registro privado
    

    O passo de build do modelo já declara o segredo opcional next_server_actions_key desta forma.

  11. Armazenar em cache o store do pnpm com uma montagem de cache BuildKit. --mount=type=cache,id=pnpm-store,target=/pnpm/store em fetch/install/dlx, com pnpm_config_store_dir=/pnpm/store. O store sobrevive entre builds no mesmo builder sem ir para uma camada. No CI, o cache de camada é type=gha (veja github-actions).

  12. .dockerignore na raiz do repositório mantém o contexto pequeno e segredos fora. Exclui node_modules, .next, .turbo, dist, coverage, .env*, .git, .github, charts. Um contexto que inclui node_modules do Windows ou macOS quebra pacotes nativos na imagem Linux.

  13. Multi-arquitetura é linux/amd64,linux/arm64, construído pelo CI. Localmente, construa para sua própria arquitetura. Cada estágio é neutro em relação à arquitetura, exceto o download do pnpm, que seleciona seu checksum a partir de TARGETARCH.

  14. Rótulos: o Dockerfile define org.opencontainers.image.title e licenses; o CI adiciona source, revision, version, created através de docker/metadata-action. Não codifique um rótulo de versão.

  15. Manter estágios livres de hacks específicos do aplicativo. Sem apk add no runner (o aplicativo não precisa de um conjunto de ferramentas de shell), sem npm, sem node_modules copiados do host. Se o aplicativo precisar de uma ferramenta nativa em tempo de execução, justifique-a em um comentário.

Depuração

SintomaCausa
extends: … doesn't resolve durante a construçãoUm arquivo de nível raiz que o aplicativo precisa não estava na árvore podada: mova-o para um pacote do workspace
ERR_PNPM_OUTDATED_LOCKFILE em depsLockfile não commitado após uma alteração de manifesto
ERR_PNPM_IGNORED_BUILDSUma nova dependência quer um script de instalação: decida em allowBuilds
Aplicativo inicia, sem CSS/JS.next/static ou public não copiado para apps/<app>/
Sondagem de saúde falha, logs normaisHOSTNAME não é 0.0.0.0
EROFS em tempo de execuçãoAlgo escreve fora de .next/cache; encontre, não remova --read-only
NEXT_PUBLIC_X vazioNão passado como argumento de build (é assado no build)

Verificação

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>   # healthy após ~30s
docker rm -f <app>

Fontes

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.

Habilidades Relacionadas