// DevOps
Despliegue moderno de Next.js: GitHub Actions, Docker y cero tiempo de inactividad
Publicado el 02.03.2026
Si todavía haces next build directamente en el servidor de producción — tu servidor realmente sufre. CPU al máximo, OOM-kill, errores 502 y largos tiempos de inactividad — es un clásico que ya es hora de terminar.
En 2026, el estándar de la industria es la construcción separada:
- Construimos una imagen standalone mínima en la nube con GitHub Actions.
- La empujamos a GHCR (GitHub Container Registry).
- En el servidor solo hacemos pull + reinicio atómico.
Capítulo 1. Dockerfile ideal (multietapa + standalone)
Todo el secreto de una imagen pequeña y rápida está en el modo standalone. Next.js calcula por sí mismo qué archivos y partes de node_modules son realmente necesarios para que funcione el servidor, y copia solo esos.
# syntax=docker/dockerfile:1
# ETAPA 1 — Dependencias
FROM node:24-alpine AS deps
WORKDIR /app
COPY package.json yarn.lock* pnpm-lock.yaml* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else npm ci; \
fi
# ETAPA 2 — Compilación
FROM node:24-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# ETAPA 3 — Imagen de producción (Runner)
FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Seguridad ante todo: no ejecutar como root
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs
# Copiamos solo los artefactos de la compilación standalone
COPY --from=builder --chown=nextjs:nodejs /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"
# Comprobación de salud del contenedor
HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
CMD ["node", "server.js"]
¿Por qué es genial?
- Tamaño: La imagen pesa ~200 MB frente a 1.5 GB de la habitual.
- Seguridad: Usar un usuario
non-root(nextjs) protege el sistema anfitrión en caso de compromiso del contenedor. - Healthcheck: Docker detectará si la aplicación se ‘colgó’ al iniciar y no enviará tráfico a ella.
Capítulo 2. Análisis del workflow de GitHub Actions
Tu pipeline está dividido en dos etapas (jobs): la construcción en la nube y el despliegue en tu “hardware”.
1. Preparación y build
- name: Docker meta & tags
id: prepare
run: |
IMAGE_REPO="ghcr.io/${GITHUB_REPOSITORY,,}"
SHORT_SHA="${GITHUB_SHA::8}"
echo "image_repo=$IMAGE_REPO" >> $GITHUB_OUTPUT
echo "image_tag=sha-$SHORT_SHA" >> $GITHUB_OUTPUT
Importante: La sintaxis ${GITHUB_REPOSITORY,,} convierte el nombre del repositorio a minúsculas. Los registros de Docker no aceptan mayúsculas, y en GitHub a menudo las hay.
2. Caché de la compilación
cache-from: type=gha
cache-to: type=gha,mode=max
Usamos el caché nativo de GitHub Actions. Si no has cambiado package.json, la etapa de instalación de dependencias se omitirá y el build durará 1–2 minutos en lugar de 10.
3. Despliegue inteligente (bucle de healthcheck)
El punto más importante — no solo decimos al servidor “actualízate”, comprobamos si la aplicación sobrevivió.
for i in {1..60}; do
STATUS=$(docker inspect --format='{{json .State.Health.Status}}' nextjs 2>/dev/null || echo '"not-found"')
if [[ $STATUS == '"healthy"' || $STATUS == '"no-healthcheck"' ]]; then
HEALTHY=1
break
fi
sleep 2
done
Si Next.js se cae por un error en las variables de entorno, el script lo detectará, no actualizará el proxy (Caddy/Nginx) y terminará la acción con error. Tu sitio antiguo seguirá funcionando y recibirás una notificación del problema.
Capítulo 3. Variables en tiempo de ejecución vs en tiempo de compilación
Estas son las trampas en las que casi todos caen.
NEXT_PUBLIC_(Build-time): Estas variables se “incrustan” en el bundle JS durante el comandonext build. Si las cambias en el servidor en.env, no cambiará nada. Debes pasarlas en GitHub Actions comobuild-args.Secretos (Runtime):
DATABASE_URL,JWT_SECRET. No se deben meter en la imagen Docker. Se inyectan en el momento de arrancar el contenedor mediantedocker-compose.
Consejo: Si es posible, haz que la URL de la API también sea una variable en tiempo de ejecución mediante proxy o scripts de configuración especiales, para que la misma imagen pueda desplegarse tanto en staging como en producción sin reconstrucción.
// Reviews
Reseñas relacionadas
Llegué con una solicitud costosa para la configuración de un servidor VPS, pero durante la consulta Mikhail propuso una solución mucho más sencilla y económica. Al final ahorré dinero y tiempo. Mikhail — un verdadero experto que trabaja por el resultado del cliente, no por la factura. ¡Lo recomiendo!
Llegué con una solicitud costosa para la configuración de un servidor VPS, pero durante la consulta Mikhail propuso una solución mucho más simple y económica. Al final ahorré presupuesto y tiempo. Mikhail es un …
Configuración de VPS, configuración del servidor
12.05.2026 · ★ 5/5
¡Excelente trabajo! Configuró el servidor muy rápido, instaló el panel y configuró la IP. ¡Sin duda lo recomiendo!
¡Excelente trabajo! Muy rápido configuró el servidor, instaló el panel y configuró la IP. ¡Sin duda lo recomiendo!
Configuración de VPS, configuración del servidor
19.04.2026 · ★ 5/5
Todo perfecto, ayudó de forma rápida y profesional, gracias, lo recomiendo a la comunidad
Todo perfecto, ayudó de forma rápida y profesional, gracias, lo recomiendo a la comunidad
Configuración de VPS, configuración del servidor
16.04.2026 · ★ 5/5
Hubo varios problemas, tanto en la parte técnica como en la comprensión general. Mijaíl respondió rápido a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos; por ello, muchas gracias. Estoy satisfecho con el resultado.
Hubo varios problemas relacionados tanto con la parte técnica como con la comprensión en general. Mijaíl respondió rápidamente a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos, por lo que le …
Configuración de VPS, configuración del servidor
18.02.2026 · ★ 5/5
Todo se hizo de manera rápida y precisa. Lo recomiendo.
Todo se hizo rápido y con precisión. Lo recomiendo.
Configuración de VPS, configuración del servidor
17.01.2026 · ★ 5/5
Todo salió bien, el profesional respondió rápidamente a las preguntas y ayudó a resolver el problema. ¡Gracias!
Todo fue bien, el profesional respondió rápidamente a las preguntas y ayudó a resolver el problema. ¡Gracias!
Configuración de VPS, configuración del servidor
16.12.2025 · ★ 5/5
// Contact
¿Necesitas ayuda?
Escríbeme y te ayudaré a resolver el problema
// Related