Funcionamiento
Preparar tu aplicación
Lee el puerto de process.env.PORT
No fijes el puerto en el código. Escucha en 0.0.0.0, nunca en localhost. Si se ignora: El enrutador entrega en el puerto declarado y nadie responde. El visitante recibe un 502 con el contenedor sano.
Ejecuta las migraciones al iniciar, no durante el build
Un migrate deploy antes de arrancar el servidor. Mientras se construye la imagen no hay base de datos a la que conectarse. Si se ignora: La base queda con cero tablas y la app da error en la primera consulta. Fue el fallo más común en las migraciones reales.
Falla de forma visible cuando falle la migración
Si el migrate da error, el proceso debe terminar con el mensaje en el log, no arrancar de todos modos. Si se ignora: La app sigue en línea sirviendo errores, el panel se ve en verde y nadie lo nota hasta que un cliente se queja.
Las variables NEXT_PUBLIC_* son argumentos de build
En Next.js se graban dentro del paquete durante el build. Declara cada una como ARG y promuévela a ENV antes de la línea que construye. Si se ignora: El valor de desarrollo queda incrustado para siempre. La web de producción sigue apuntando a localhost.
Nada importante en el disco del contenedor
Subidas, imágenes, adjuntos: envíalos al almacenamiento S3. El disco del contenedor desaparece cuando se recrea la copia. Si se ignora: Los archivos desaparecen en la siguiente publicación, sin aviso y sin forma de recuperarlos.
No guardes estado solo en la memoria del proceso
Sesión, cola, caché compartida: ponlas en la base de datos o en Redis. Con más de una copia, cada proceso tiene su propia memoria. Si se ignora: El usuario pierde la sesión cada vez que una petición cae en otra copia, y las escrituras desaparecen sin ningún error.
Un planificador integrado exige una sola copia
Si la app tiene un cron interno, díselo a quien vaya a publicarla. La alternativa es mover la tarea a un servicio propio. Si se ignora: Cobros duplicados, mensajes enviados dos veces, clientes bloqueados por error.
Responde algo en /
Cualquier respuesta por debajo de 500 sirve, incluso una redirección al login. Así sabe la plataforma que la app está viva. Si se ignora: La app se considera caída y el dueño recibe un aviso de caída que no existe.
Logs en stdout, sin archivo
Escribe en la salida estándar. No abras un archivo de log dentro del contenedor. Si se ignora: El log queda atrapado en un disco al que nadie llega, justo cuando lo necesitas.
Todo secreto viene del entorno
Clave de API, secreto de token, credencial de terceros: solo desde variables de entorno. Nunca en el repositorio, nunca con un valor por defecto que funcione. Si se ignora: El secreto se filtra en el repositorio y sirve para cualquiera que clone el código.
Monorepo: un servicio por programa, en el mismo proyecto
La web y la API del mismo repositorio entran como dos servicios del mismo proyecto, cada uno con su Dockerfile y su puerto. No crees dos proyectos. Si se ignora: Con dos proyectos, los secretos hay que copiarlos a mano de uno a otro, y el día en que se cambia uno y no el otro, el token deja de aceptarse y nadie entiende por qué.
Dockerfile: indica la ruta y deja el contexto en la raíz
En un monorepo, indica la ruta completa del Dockerfile del servicio. El contexto sigue en la raíz para encontrar el lockfile compartido. Si se ignora: El build muere con "open Dockerfile: no such file or directory" en un repositorio que sí tiene Dockerfile.