Next.js
Output y self-hosting
Explica next start, output standalone y static export, junto con Docker, proxies, réplicas, caché compartida, health checks y operación segura.
- Última actualización
- Actualizada
- Nivel
- Profundización
Next.js
Explica next start, output standalone y static export, junto con Docker, proxies, réplicas, caché compartida, health checks y operación segura.
Self-hosting Next.js significa operar un runtime completo: proceso Node, reverse proxy, assets, optimizador de imágenes, cachés, revalidation, múltiples réplicas, health checks, shutdown, logs y despliegues compatibles. Ejecutar un contenedor es solo una pieza; la plataforma administrada resolvía varias de estas responsabilidades de forma implícita.
Ejecuta el output de next build con servidor Next.js:
pnpm next build
pnpm next startAdecuado para una VM/contenedor con node_modules y .next disponibles.
const nextConfig: NextConfig = {
output: "standalone",
};Genera .next/standalone con archivos traced necesarios y un server.js mínimo. Debes copiar también:
.next/static → .next/standalone/.next/static
public → .next/standalone/publicO servir estáticos desde CDN.
output: "export"Produce archivos estáticos sin runtime Next.js. No soporta capacidades que requieren servidor, como request-time rendering, Actions, muchas Dynamic APIs u optimizador runtime por defecto.
Internet
→ CDN/WAF/load balancer
→ reverse proxy
→ Next.js replicas
→ shared cache/storage/databaseEl proxy gestiona TLS, compresión, límites y headers. Las réplicas deben ser stateless salvo caches deliberadas.
FROM node:24-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
FROM node:24-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build
FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
USER node
EXPOSE 3000
CMD ["node", "server.js"]Adapta versiones/usuario y añade init si la plataforma no reenvía señales correctamente. No incluyas .env o secretos de build innecesarios en la imagen.
Secrets privados pueden inyectarse al iniciar el contenedor. Valores NEXT_PUBLIC_* ya quedaron fijados durante build.
Promover la misma imagen entre entornos funciona para secretos runtime, no para configuración pública inline sin otra estrategia.
Configura:
X-Forwarded-Proto/Host desde infraestructura confiable.Sobrescribe headers forwarded del cliente para evitar spoofing.
¿El proceso está vivo?
¿Puede recibir tráfico? Puede comprobar configuración y dependencias esenciales con límites, sin ejecutar una query costosa en cada segundo.
No uses home como health endpoint: puede depender de CMS/caché y ocultar la salud del proceso.
Al recibir SIGTERM:
stop accepting traffic
→ finish active requests
→ close server/pools
→ flush telemetry
→ exit before deadlineSi el load balancer sigue enviando tráfico durante termination, aparecen errores. Coordina readiness/preStop y timeout.
Memoria local no se comparte:
replica A invalidates
replica B still has cached valueNext.js permite personalizar cache handler para almacenamiento compartido según versión/modelo. Decide:
No uses Redis como reemplazo ciego de todas las caches.
En varias instancias, tags y regeneraciones necesitan coordinación. Un filesystem local generado por A no existe en B.
Usa storage/cache compartida o afinidad solo si sus trade-offs son aceptables. Prueba deploy rolling e invalidación concurrente.
/_next/image consume CPU y caché. En self-hosting:
sharp.Alternativamente usa un CDN de imágenes con loader custom.
/_next/static tiene nombres hashed y puede cachearse de forma inmutable. HTML/RSC no debe recibir la misma regla. Configura CDN para no servir chunks antiguos incorrectamente durante despliegues.
Retén assets de releases anteriores el tiempo suficiente para pestañas abiertas y despliegues rolling.
build image once
→ start new replicas
→ readiness passes
→ switch traffic
→ drain old replicasNo modifiques archivos bajo instancias en ejecución. Mantén rollback al artefacto anterior y migrations compatibles.
Ejecútalas como job único controlado, no desde cada réplica al arrancar. Usa expand-contract para que versión vieja y nueva convivan durante rollout.
Usa cookies firmadas o store compartida. No almacenes sesiones en memoria local de una réplica salvo sticky sessions deliberadas, que reducen resiliencia.
Uploads van a object storage; filesystem local es efímero en orquestadores.
Un server.js personalizado permite integrar Next.js en servidor propio, pero puede desactivar Automatic Static Optimization y complicar upgrades/deployment. Úsalo cuando necesitas una capacidad que Proxy, Route Handlers o infraestructura no resuelven.
No lo agregues solo para redirects o headers.
El reverse proxy puede terminar HTTP/2 y hablar HTTP/1.1 con Node. Lo importante es no bufferizar indebidamente. Verifica chunks en producción porque algunos proxies comprimen antes de enviar y retrasan el stream.
Mide por réplica/release:
Propaga request IDs desde el proxy.
Es buena opción cuando:
Ventaja: hosting simple/CDN. Trade-off: cualquier dinámica pasa al cliente o a servicios externos.
Docker Next.js standalone
→ Nginx/managed load balancer
→ 3 replicas
→ PostgreSQL managed
→ Redis cache handler only where needed
→ S3-compatible uploads
→ CDN for static and imagesSin cache compartida, cada réplica puede ser correcta pero menos eficiente; con invalidación local, puede ser incorrecta. Distingue consistencia de optimización.
Faltan assets.
Datos divergen.
Varias instancias compiten.
Streaming desaparece.
Causa carga/caídas.
Requests fallan en deploy.
ChunkLoadError.
Datos no durables.
Pierde optimizaciones y aumenta mantenimiento.
.next/standalone?.next/static y normalmente public.Despliegue en Vercel compara estas responsabilidades con una plataforma integrada.