Busque em todas as páginas da documentação
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Implante uma aplicação Next.js 15+ App Router usando o modo de saída standalone, contêineres Docker, funções de runtime de borda e otimizações específicas da plataforma.
// next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
};
export default nextConfig;# Construa a aplicação
npm run build
# A saída standalone está em .next/standalone
# Copie os ativos estáticos e públicos
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
# Execute o servidor standalone
node .next/standalone/server.js# Dockerfile
FROM node:20-alpine AS base
# Instale as dependências
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Construa a aplicação
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# Imagem de produção
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]# docker-compose.yml
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- AUTH_SECRET=your-secret-here
depends_on:
- db
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:// app/api/geo/route.ts
import { NextRequest, NextResponse } from "next/server";
export const runtime = "edge";
export async function GET(request: NextRequest) {
return NextResponse.json({
city: request.geo?.city ?? "unknown",
country: request.geo?.country ?? "unknown",
region: request.geo?.region ?? "unknown",
});
}// middleware.ts
import { NextRequest, NextResponse } from "next/server";
// Middleware sempre roda na borda
export function middleware(request: NextRequest) {
const country = request.geo?.country ?? "US";
const response = NextResponse.next();
response.headers.set("x-user-country", country);
return response;
}// package.json
{
"scripts": {
"build": "next build",
"analyze": "ANALYZE=true next build",
"start": "next start",
"start:standalone": "node .next/standalone/server.js"
}
}// next.config.ts (com bundle analyzer)
import type { NextConfig } from "next";
import withBundleAnalyzer from "@next/bundle-analyzer";
const nextConfig: NextConfig = {
output: "standalone",
};
export default withBundleAnalyzer({
enabled: process.env.ANALYZE === "true",
})(nextConfig);output: "standalone" produz um build autocontido que inclui apenas os arquivos node_modules necessários. A saída em .next/standalone pode ser executada apenas com node server.js, sem precisar do diretório node_modules completo..next/static) e public/ não estão incluídos na saída standalone. Eles devem ser copiados separadamente ou servidos de uma CDN.fs, Buffer ou módulos nativos.HOSTNAME="0.0.0.0" é necessário no Docker para aceitar conexões de fora do contêiner. Sem ele, o servidor se vincula a 127.0.0.1 e fica inacessível.Exportação Estática (Sem Servidor):
// next.config.ts
const nextConfig: NextConfig = {
output: "export",
};Isso gera um site totalmente estático no diretório out/. Nenhum servidor Node.js é necessário. Limitações: sem Server Components no tempo de requisição, sem rotas de API, sem middleware, sem ISR.
Implantação no Vercel:
# Instale o Vercel CLI
npm i -g vercel
# Implante (detecta automaticamente o Next.js)
vercel
# Implante em produção
vercel --prodO Vercel lida automaticamente com a saída standalone, funções de borda e distribuição de CDN. Nenhum Dockerfile é necessário.
Endpoint de Verificação de Integridade Personalizado:
// app/api/health/route.ts
import { NextResponse } from "next/server";
export async function GET() {
return NextResponse.json({
status: "ok",
timestamp: new Date().toISOString(),
version: process.env.APP_VERSION ?? "unknown",
});
}request.geo é tipado como { city?: string; country?: string; region?: string; latitude?: string; longitude?: string } | undefined. Ele só é preenchido em implantações de borda (Vercel, Cloudflare).runtime deve ser uma string literal ("edge" ou "nodejs"). Não pode ser uma variável.public/ ou .next/static/. Você deve copiar esses diretórios para a saída standalone ou servi-los de uma CDN.fs, path, child_process, crypto (use globalThis.crypto) e a maioria dos módulos nativos não estão disponíveis. Consulte a referência da API do Edge Runtime do Next.js.docker run -e KEY=value) e acesse-as via process.env no código do servidor. Variáveis NEXT_PUBLIC_ são sempre apenas para tempo de build./_next/static/ e /public/.output: "export" desabilita todos os recursos do servidor. Sem Server Components no tempo de requisição, sem Route Handlers, sem middleware, sem ISR. Use apenas para sites totalmente estáticos.sharp às suas dependências: npm install sharp.| Abordagem | Prós | Contras |
|---|---|---|
| Vercel | Zero configuração, nativo de borda, CDN automático | Dependência de fornecedor, custo em escala |
| Docker + standalone | Portátil, qualquer provedor de nuvem | Configuração manual de infra, sem borda por padrão |
Exportação estática (output: "export") | Sem servidor, hospedagem barata (S3, Cloudflare) | Sem recursos de servidor |
| AWS Amplify | Gerenciado, suporta SSR | Configuração de borda limitada, específico da AWS |
| Cloudflare Pages | Foco em borda, rápido, generoso nível gratuito | Suporte limitado à API do Node.js |
| Railway ou Fly.io | Baseado em Docker, DX simples | Ecossistema menor |
node_modules necessários.node server.js, sem o diretório node_modules completo.127.0.0.1 (apenas localhost).127.0.0.1 é inacessível de fora do contêiner.HOSTNAME="0.0.0.0" faz com que o servidor aceite conexões de qualquer interface de rede.fs, path, child_process ou Buffer.globalThis.crypto em vez do módulo crypto do Node.js.NEXT_PUBLIC_ são substituídos estaticamente no tempo de next build.NEXT_PUBLIC_ mudar.out/ sem a necessidade de um servidor.npm install sharp ou as imagens falharão na otimização.export const runtime = "edge";
// ou
export const runtime = "nodejs";"edge" | "nodejs".deps) instala apenas as dependências de produção.builder) copia as dependências e constrói a aplicação.runner) copia apenas a saída standalone, reduzindo o tamanho final da imagem.server.js standalone é um servidor Node.js mínimo focado em SSR.export async function GET(request: NextRequest) {
const city = request.geo?.city ?? "unknown";
}request.geo só é preenchido em implantações de borda (Vercel, Cloudflare).undefined no desenvolvimento local e em implantações Node.js não-edge.{ status: "ok" } com metadados opcionais.Revisado por Chris St. John·Última atualização: 7 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥