5.3Docker para Node.js
Lo esencial en 30 segundos
- Fin del « en mi máquina funciona » : el contenedor lleva la app con su entorno y corre idéntico en todas partes.
- Imagen → contenedor : el Dockerfile describe la receta, docker build fija la imagen, docker run lanza el contenedor.
- Compose para la pila : app + base + caché descritos en un archivo y lanzados juntos — incorporación en un comando.
Mini-caso hilado — Salim conteneriza en Argel
La API de Salim corre perfecta en su puesto en Argel — pero falla en el de su colega (versión de Node distinta, variable faltante). Escribe un Dockerfile : imagen base Node, dependencias instaladas en la imagen, comando de arranque. Luego un archivo Compose con la base de datos : un solo lanzamiento monta toda la pila. Continuación de los casos 5.1-5.2 — Salim vuelve su app reproducible en todas partes.
Continuación de los casos 5.1-5.2 — Salim pasa de « en mi casa funciona » a « igual en todas partes ».
1. Contenerizar : imagen y contenedor
Docker resuelve el « en mi máquina funciona » empaquetando la aplicación con todo su entorno (versión de Node, dependencias, configuración) en un contenedor aislado y portable, que corre idéntico en todas partes : puesto, colega, servidor, nube. Conceptos : la imagen (modelo fijo de la app + entorno, definido por un Dockerfile — la receta : imagen base Node, copiar el código, instalar las dependencias, comando de arranque) y el contenedor (instancia en ejecución de una imagen). Se construye (docker build), se lanza (docker run). El .dockerignore excluye lo inútil de la imagen (node_modules — las dependencias se instalan DENTRO de la imagen). Salim ya no discute versiones : el entorno viaja con el código.
Reflejo : todo lo específico de su puesto y ausente de la imagen es un futuro fallo en otro lado — la imagen debe contenerlo todo.
2. Docker Compose y beneficios
Para una pila realista (app + base + caché), Docker Compose (docker-compose.yml) define varios contenedores y sus relaciones, lanzados juntos con un comando (docker compose up). Un solo archivo describe toda la pila, reproducible idéntica — y la incorporación se vuelve trivial : un nuevo desarrollador lanza un comando y obtiene todo el entorno. Beneficios : reproductibilidad (idéntico en todas partes), aislamiento (sin conflictos entre apps y versiones), portabilidad (todo anfitrión Docker), facilidad de despliegue (desplegar = lanzar el contenedor — ver 5.4). Salim añade la base al Compose : su colega arranca en minutos.
Docker es un estándar del desarrollo moderno y una competencia transversal (DevOps) : las bases bastan para empezar, la orquestación avanzada vendrá según las necesidades.
3. La dosis justa para un desarrollador
No hace falta volverse experto en infraestructura : apunte a las bases útiles — escribir un Dockerfile simple, construir y lanzar, orquestar app + base con Compose, excluir lo inútil vía .dockerignore. Domine Node primero (su corazón de oficio), añada Docker cuando trabaje en equipo, prepare un despliegue o gestione varios servicios. A evitar : incluir node_modules en la imagen, apuntar a la orquestación avanzada antes de las bases, o contenerizar un minúsculo script de aprendizaje sin necesidad real. Salim mantiene su Dockerfile legible : seis instrucciones comprendidas valen más que una receta copiada.
El buen perfil : un desarrollador que conoce las bases de la explotación — autónomo, capaz no solo de programar sino de entregar.
¿Lo sabía?
Misma imagen, mismo comportamiento — en todas partes.
🔎 Ejemplo concreto — El Dockerfile de Salim
La receta de la imagen, legible en seis líneas.
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "app.js"]
# .dockerignore : node_modules
# docker compose up → app + base juntas
Lectura : cada instrucción tiene un papel — base, dependencias, código, arranque.
Lección : un Dockerfile comprendido vale más que una receta copiada.
Vocabulario de la sección
- Docker
- Herramienta que empaqueta la app con su entorno en un contenedor portable.
Ejemplo sencillo: La API de Salim corre igual en Argel y en casa de su colega.
Lo que no es: un simple instalador de Node en cada puesto.
Reflejo: ¿mi app aún depende de mi puesto?
- Imagen
- Modelo fijo de la app + entorno, construido desde el Dockerfile.
Ejemplo sencillo: Salim construye una imagen versionada de cada entrega.
Lo que no es: el contenedor en curso de ejecución.
Reflejo: ¿puedo reconstruir esta imagen idéntica?
- Dockerfile
- Receta de construcción de la imagen (base, código, dependencias, arranque).
Ejemplo sencillo: Seis instrucciones legibles para la API de Salim.
Lo que no es: un script que instala Node a mano en un servidor.
Reflejo: ¿cada instrucción está comprendida, no copiada?
- Contenedor
- Instancia en ejecución de una imagen, aislada y portable.
Ejemplo sencillo: Salim lanza un contenedor idéntico en dev y en pruebas.
Lo que no es: la propia imagen fija.
Reflejo: ¿dev y prod lanzan la misma imagen?
- Docker Compose
- Archivo que describe varios contenedores lanzados juntos.
Ejemplo sencillo: App + base de Salim arrancadas con un solo comando.
Lo que no es: la orquestación avanzada de tipo Kubernetes.
Reflejo: ¿un nuevo dev arranca en un comando?
En la práctica — Contenerizar una aplicación Node
- Escriba un Dockerfile : partir de una imagen Node, copiar el código, instalar las dependencias (npm install), definir el comando de arranque. Añada un .dockerignore (node_modules…).
- Construya la imagen (`docker build`) y lance un contenedor (`docker run`) ; verifique que la aplicación corre en el contenedor.
- Orqueste con Docker Compose : un docker-compose.yml que defina la app Node Y su base, lanzadas juntas (`docker compose up`).
- Disfrute los beneficios : reproductibilidad (idéntico en todas partes), aislamiento, e incorporación (un `docker compose up` basta para todo el entorno).
Guion listo para decir — proponer Docker al equipo
« Nuestra API funciona en mi puesto pero no en otro lado : es un problema de entorno, no de código. Propongo un Dockerfile simple — seis instrucciones — más un Compose con la base. Cada uno lanzará la misma imagen, y un recién llegado arrancará en un comando. Lo mantenemos legible y evitamos la orquestación avanzada por ahora. »
Para decir en reunión de equipo para hacer adoptar la contenerización sin apuntar a la pericia DevOps.
Modelo copiar-pegar — Dockerfile Node genérico
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
# .dockerignore :
# node_modules
# npm-debug.log
# .git
Solo / presupuesto pequeño
Salim solo : un Dockerfile simple sin Compose basta — la imagen ya fija el entorno.
Pyme / equipo reducido
Compose app + base : cada colega arranca la pila completa sin instalación manual.
Pyme en Argel
Salim comparte la imagen con el equipo en Argel : todos prueban la misma versión, fin de las diferencias de puesto.
Equipo que empieza
Pareja : uno escribe el Dockerfile, el otro lo relee línea por línea ; build probado en dos puestos antes de adoptarlo.
✓ Buenas prácticas
- Dominar Node primero, luego aprender las bases de Docker.
- Añadir un .dockerignore (excluir node_modules).
- Usar Docker Compose para orquestar app + base (incorporación rápida).
✗ Errores frecuentes
- Incluir node_modules en la imagen (instalarlo en la imagen vía npm install).
- Querer dominar la orquestación avanzada antes de las bases.
- Contenerizar un pequeño script de aprendizaje sin necesidad real.
Puntos clave
- DOCKER empaqueta la aplicación CON su entorno en un CONTENEDOR aislado y portable, que corre IDÉNTICO en todas partes — fin del « en mi máquina funciona ».
- IMAGEN (modelo fijo, definido por un DOCKERFILE) → CONTENEDOR (instancia). `docker build` / `docker run`. .dockerignore excluye node_modules.
- DOCKER COMPOSE define VARIOS contenedores (app + base + caché) lanzados juntos (`docker compose up`) — describe toda la pila, reproducible.
- Beneficios : REPRODUCTIBILIDAD, aislamiento, portabilidad, facilidad de despliegue, incorporación rápida. Estándar moderno (transversal DevOps).
Reto 48h — aplica mañana
Escriba el Dockerfile de su app (modelo de arriba) y láncela en contenedor : ¿responde igual que en su puesto?
- Puedo explicar imagen frente a contenedor en una frase.
- Mi Dockerfile construye una imagen que corre.
- Sé por qué node_modules no figura ahí.
Preguntas frecuentes
¿Qué aporta concretamente Docker, y es necesario para un desarrollador Node?
Docker aporta sobre todo la reproductibilidad : fin del « en mi máquina funciona » (el contenedor lleva todo, así que corre idéntico en todas partes). También : aislamiento (varias apps/versiones sin conflictos), portabilidad (todo anfitrión Docker), facilidad de despliegue (desplegar = lanzar el contenedor), incorporación rápida (un docker compose up monta toda la pila). Para aprender Node o pequeños proyectos solo, no estrictamente. Para desarrollo profesional, en equipo o con despliegue, se ha vuelto casi imprescindible — y transversal. Domine Node primero, luego las bases de Docker.
Docker, despliegue, CI/CD... ¿debo volverme experto DevOps además de desarrollador?
No, no experto — pero conocer las bases beneficia enormemente : autonomía (poner su trabajo en producción), empleabilidad (ofertas que piden Docker/despliegue/CI-CD), mejor colaboración (apps fáciles de desplegar), visión completa del ciclo. Apunte a las bases : contenerizar y Compose (no la orquestación avanzada), desplegar en una plataforma simple, un pipeline CI/CD simple, secretos y config en variables de entorno, nociones de logs/monitorización/HTTPS. El buen perfil : un desarrollador que conoce las bases de la explotación — capaz no solo de programar sino de entregar.
¿Qué problema resuelve Docker principalmente?