nextjs-despliegue-vps-docker

Despliegue de Next.js

  • 4 min

Hemos llegado al final del camino. Tenemos una aplicación rápida, optimizada y funcional. Ahora surge la gran pregunta: ¿Dónde la alojamos?

Si buscáis en Google, el 99% de los tutoriales os dirán: “Usa Vercel” (los creadores de Next.js). Vercel tienen una plataforma PaaS maravillosa. Es pulsar un botón y listo.

Pero depender de un único proveedor es un riesgo. Además, los costes de las plataformas Serverless pueden dispararse si vuestra app escala. A veces, la solución correcta es un VPS de 5€/mes o un bucket S3.

Hoy vamos a ver cómo sacar Next.js de su “casa” y desplegarlo en cualquier infraestructura 👇.

Entendiendo el Build

Antes de subir nada, debemos entender qué genera Next.js.

Cuando ejecutamos npm run build, Next.js analiza todo nuestro código y crea una carpeta oculta llamada .next.

Esta carpeta contiene:

  1. HTML estático: Para las páginas que son totalmente estáticas.
  2. Código de servidor: Archivos JS optimizados para correr en Node.js (Server Actions, SSR).
  3. Assets públicos: Imágenes, fuentes y JS del cliente.

Para arrancar la aplicación en modo producción, no usamos npm run dev. Usamos:

npm run start

Copied!

Este comando levanta un servidor Node.js local que sirve lo que hay en .next. Este es el servidor que debemos poner en internet.

Estrategia 1: El Servidor Node.js (VPS)

Si tenéis un VPS (DigitalOcean, Hetzner, AWS EC2) con Linux, podéis desplegar Next.js “a pelo”.

Subís el código al servidor (git pull).

Instaláis dependencias: npm install --production.

Construís: npm run build.

Ejecutáis: npm run start.

El problema es que si cerráis la terminal SSH, el servidor se apaga. Para mantenerlo vivo, necesitáis un gestor de procesos como PM2.

npm install -g pm2
pm2 start npm --name "mi-app-next" -- start

Copied!

Esta estrategia es frágil. Si actualizáis la versión de Node en el servidor, la app puede romperse. Para evitar el “en mi máquina funciona”, usamos Docker.

Estrategia 2: Docker

Docker nos permite empaquetar nuestra aplicación, con su versión exacta de Node.js y sus dependencias, en un contenedor inmutable.

El truco para que la imagen de Docker no pese 1GB es usar una funcionalidad de Next.js llamada Standalone Output.

const nextConfig = {
  // Esto le dice a Next.js que genere un build aislado con
  // SOLO los node_modules necesarios para producción.
  output: "standalone",
};

export default nextConfig;

Copied!

No copiéis un Dockerfile básico. Usad este optimizado (Multi-stage build):

# ETAPA 1: Dependencias
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# ETAPA 2: Builder
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

# ETAPA 3: Runner (Imagen final minúscula)
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV production

# Copiamos solo lo necesario desde el builder
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/.next/standalone ./

EXPOSE 3000
CMD ["node", "server.js"]

Copied!

Con esto, tenéis una imagen ligera que podéis desplegar en cualquier sitio: Kubernetes, AWS ECS, Google Cloud Run o vuestro VPS con Docker Compose.

Estrategia 3: Static Exports (SSG)

A veces, no necesitáis un servidor. Si vuestra web es un Blog, una Landing Page o documentación corporativa, no necesitáis Node.js corriendo 24/7. Podéis pre-renderizar todo a HTML y CSS.

// next.config.mjs
const nextConfig = {
  output: "export", // 👈 La clave
};

Copied!

Al ejecutar npm run build, Next.js ya no creará la carpeta .next. Creará una carpeta out.

Dentro de out tendréis index.html, about.html, etc.

La carpeta out se puede alojar gratis o por céntimos en:

  • GitHub Pages
  • AWS S3 + CloudFront
  • Nginx / Apache (Servidor web clásico)
  • Cloudflare Pages

Limitaciones

Al no haber servidor Node.js, perdéis:

  • ❌ Server Actions (los formularios no funcionarán sin una API externa).
  • ❌ Renderizado Dinámico (no podéis leer headers ni cookies en el servidor).
  • ❌ Optimización dinámica de Imágenes <Image> con el servidor de Next.js (necesitáis imágenes sin optimizador o un loader externo como Cloudinary).

Resumen ¿Qué elijo?

Guía de decisión para cuando tengáis que llevar vuestro proyecto a producción:

EscenarioEstrategia Recomendada¿Por qué?
Landing Page / Blog personalStatic ExportCoste cero, imposible de hackear, velocidad máxima.
SaaS / E-commerceDocker (VPS/Cloud)Control total, soporte para Server Actions y BBDD. Coste predecible.
MVP Rápido / HackathonVercel / NetlifyDespliegue en 1 minuto, CI/CD automático. Cuidado con el escalado de costes.