Conteneriza una aplicación Node.js
Requisitos previos
Antes de comenzar, asegúrate de que las siguientes herramientas estén instaladas y disponibles en tu sistema:
- Has instalado la última versión de Docker Desktop.
- Tienes un cliente de git. Los ejemplos de esta sección utilizan un cliente de git basado en la línea de comandos, pero puedes usar cualquier cliente.
¿Eres nuevo en Docker?
Comienza con la guía de conceptos básicos de Docker para familiarizarte con conceptos clave como imágenes, contenedores y Dockerfiles.
Descripción general
Esta guía te acompaña a lo largo del proceso completo de contenerización de una aplicación Node.js con Docker. Aprenderás a crear una imagen de Docker lista para producción utilizando las mejores prácticas que mejoran el rendimiento, la seguridad, la escalabilidad y la eficiencia operativa.
Al final de esta guía, lograrás:
- Contenerizar una aplicación Node.js usando Docker.
- Crear y optimizar un Dockerfile adaptado a entornos Node.js.
- Utilizar construcciones multi-etapa (multi-stage builds) para separar las dependencias y reducir el tamaño de la imagen.
- Configurar el contenedor para un tiempo de ejecución seguro y eficiente utilizando un usuario no root.
- Seguir las mejores prácticas para construir imágenes de Docker seguras, ligeras y fáciles de mantener.
Obtén la aplicación de ejemplo
Clona la aplicación de ejemplo para usarla con esta guía. Abre una terminal, cambia al directorio en el que deseas trabajar y ejecuta el siguiente comando para clonar el repositorio de git:
$ git clone https://github.com/kristiyan-velkov/docker-nodejs-sample
Genera un Dockerfile
Docker proporciona una herramienta de CLI interactiva llamada docker init que ayuda a estructurar los archivos de configuración necesarios para contenerizar tu aplicación. Esto incluye generar un Dockerfile, .dockerignore, compose.yaml y README.Docker.md.
Para comenzar, navega a la raíz del directorio de tu proyecto:
$ cd docker-nodejs-sample
Luego ejecuta el siguiente comando:
$ docker init
Verás una salida similar a:
Welcome to the Docker Init CLI
This utility will walk you through creating the following files with sensible defaults for your project:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md
Let's get started!La CLI te hará algunas preguntas sobre la configuración de tu aplicación. Para mantener la coherencia, utiliza las mismas respuestas que se muestran en el siguiente ejemplo cuando se te solicite:
| Pregunta | Respuesta |
|---|---|
| What application platform does your project use? | Node |
| What version of Node do you want to use? | 24.11.1-alpine |
| Which package manager do you want to use? | npm |
| Do you want to run "npm run build" before starting server? | yes |
| What directory is your build output to? | dist |
| What command do you want to use to start the app? | npm run dev |
| What port does your server listen on? | 3000 |
Después de completarlo, el directorio de tu proyecto contendrá los siguientes archivos nuevos:
├── docker-nodejs-sample/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── compose.yaml
│ └── README.Docker.mdCrea un archivo de Docker Compose
Aunque docker init genera un archivo compose.yaml básico, necesitarás crear una configuración más completa para esta aplicación full-stack. Reemplaza el archivo compose.yaml generado por una configuración lista para producción.
Crea un nuevo archivo llamado compose.yml en la raíz de tu proyecto:
# ========================================
# Configuración de Docker Compose
# Aplicación de tareas (Todo) moderna en Node.js
# ========================================
services:
# ========================================
# Servicio de desarrollo
# ========================================
app-dev:
build:
context: .
dockerfile: Dockerfile
target: development
container_name: todoapp-dev
ports:
- '${APP_PORT:-3000}:3000' # Servidor API
- '${VITE_PORT:-5173}:5173' # Servidor de desarrollo de Vite
- '${DEBUG_PORT:-9229}:9229' # Depurador de Node.js
environment:
NODE_ENV: development
DOCKER_ENV: 'true'
POSTGRES_HOST: db
POSTGRES_PORT: 5432
POSTGRES_DB: todoapp
POSTGRES_USER: todoapp
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-todoapp_password}'
ALLOWED_ORIGINS: '${ALLOWED_ORIGINS:-http://localhost:3000,http://localhost:5173}'
volumes:
- ./src:/app/src:ro
- ./package.json:/app/package.json
- ./vite.config.ts:/app/vite.config.ts:ro
- ./tailwind.config.js:/app/tailwind.config.js:ro
- ./postcss.config.js:/app/postcss.config.js:ro
depends_on:
db:
condition: service_healthy
develop:
watch:
- action: sync
path: ./src
target: /app/src
ignore:
- '**/*.test.*'
- '**/__tests__/**'
- action: rebuild
path: ./package.json
- action: sync
path: ./vite.config.ts
target: /app/vite.config.ts
- action: sync
path: ./tailwind.config.js
target: /app/tailwind.config.js
- action: sync
path: ./postcss.config.js
target: /app/postcss.config.js
restart: unless-stopped
networks:
- todoapp-network
# ========================================
# Servicio de producción
# ========================================
app-prod:
build:
context: .
dockerfile: Dockerfile
target: production
container_name: todoapp-prod
ports:
- '${PROD_PORT:-8080}:3000'
environment:
NODE_ENV: production
POSTGRES_HOST: db
POSTGRES_PORT: 5432
POSTGRES_DB: todoapp
POSTGRES_USER: todoapp
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-todoapp_password}'
ALLOWED_ORIGINS: '${ALLOWED_ORIGINS:-https://tudominio.com}'
depends_on:
db:
condition: service_healthy
restart: unless-stopped
deploy:
resources:
limits:
memory: '${PROD_MEMORY_LIMIT:-2G}'
cpus: '${PROD_CPU_LIMIT:-1.0}'
reservations:
memory: '${PROD_MEMORY_RESERVATION:-512M}'
cpus: '${PROD_CPU_RESERVATION:-0.25}'
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
networks:
- todoapp-network
profiles:
- prod
# ========================================
# Servicio de base de datos PostgreSQL
# ========================================
db:
image: postgres:18-alpine
container_name: todoapp-db
environment:
POSTGRES_DB: '${POSTGRES_DB:-todoapp}'
POSTGRES_USER: '${POSTGRES_USER:-todoapp}'
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD:-todoapp_password}'
volumes:
- postgres_data:/var/lib/postgresql
ports:
- '${DB_PORT:-5432}:5432'
restart: unless-stopped
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-todoapp} -d ${POSTGRES_DB:-todoapp}']
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
networks:
- todoapp-network
# ========================================
# Configuración de volúmenes
# ========================================
volumes:
postgres_data:
name: todoapp-postgres-data
driver: local
# ========================================
# Configuración de red
# ========================================
networks:
todoapp-network:
name: todoapp-network
driver: bridgeEsta configuración de Docker Compose incluye:
- Servicio de desarrollo (
app-dev): Entorno de desarrollo completo con recarga en caliente (hot reload), soporte de depuración y montajes de tipo bind (bind mounts). - Servicio de producción (
app-prod): Despliegue de producción optimizado con límites de recursos y endurecimiento de seguridad (security hardening). - Servicio de base de datos (
db): PostgreSQL 18 con almacenamiento persistente y comprobaciones de estado. - Redes: Red aislada para una comunicación segura entre servicios.
- Volúmenes: Almacenamiento persistente para los datos de la base de datos.
Crea la configuración del entorno
Crea un archivo .env para configurar los ajustes de tu aplicación:
$ cp .env.example .env
Actualiza el archivo .env con tus preferencias:
# Configuración de la aplicación
NODE_ENV=development
APP_PORT=3000
VITE_PORT=5173
DEBUG_PORT=9229
# Configuración de producción
PROD_PORT=8080
PROD_MEMORY_LIMIT=2G
PROD_CPU_LIMIT=1.0
PROD_MEMORY_RESERVATION=512M
PROD_CPU_RESERVATION=0.25
# Configuración de la base de datos
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_DB=todoapp
POSTGRES_USER=todoapp
POSTGRES_PASSWORD=todoapp_password
DB_PORT=5432
# Configuración de seguridad
ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173Construye la imagen de Docker
El Dockerfile predeterminado generado por docker init proporciona una base confiable para aplicaciones Node.js estándar. Sin embargo, dado que este proyecto es una aplicación TypeScript full-stack que incluye tanto una API backend como componentes React de frontend, el Dockerfile debe ser personalizado para soportar y optimizar mejor esta arquitectura específica.
Revisa los archivos generados
En el siguiente paso, mejorarás el Dockerfile y los archivos de configuración siguiendo las mejores prácticas:
- Utiliza construcciones multi-etapa para mantener la imagen final limpia y pequeña.
- Mejora el rendimiento y la seguridad incluyendo únicamente lo necesario.
Estas actualizaciones hacen que tu aplicación sea más fácil de desplegar y más rápida de cargar.
NoteUn
Dockerfilees un archivo de texto plano que contiene instrucciones paso a paso para construir una imagen de Docker. Automatiza el empaquetado de tu aplicación junto con sus dependencias y entorno de ejecución.
Para obtener detalles completos, consulta la referencia de Dockerfile.
Paso 1: Configura el Dockerfile
Antes de crear un Dockerfile, debes elegir una imagen base. Puedes utilizar la imagen oficial de Node.js o una Imagen Endurecida de Docker (DHI) del catálogo de imágenes endurecidas.
Elegir una DHI ofrece la ventaja de contar con una imagen lista para producción que es ligera y segura. Para más información, consulta Docker Hardened Images.
ImportantEsta guía utiliza una etiqueta de imagen estable LTS de Node.js que se considera segura en el momento de escribir la guía. Dado que se publican nuevas versiones y parches de seguridad con regularidad, la etiqueta mostrada aquí podría no ser la opción más segura cuando sigas la guía. Revisa siempre las últimas etiquetas de imagen disponibles y selecciona una versión segura y actualizada antes de construir o desplegar tu aplicación.
Imágenes oficiales de Node.js en Docker: https://hub.docker.com/_/node
Las imágenes endurecidas de Docker (DHIs) para Node.js están disponibles en el catálogo de Docker Hardened Images. Las Docker Hardened Images están disponibles de forma gratuita para todos sin necesidad de suscripción. Puedes descargarlas y utilizarlas como cualquier otra imagen de Docker tras iniciar sesión en el registro de DHI. Para más información, consulta la guía de inicio rápido de DHI.
Inicia sesión en el registro de DHI:
$ docker login dhi.io
Descarga la DHI de Node.js (consulta el catálogo para ver las versiones disponibles):
$ docker pull dhi.io/node:24-alpine3.22-dev
En el siguiente Dockerfile, la instrucción FROM utiliza dhi.io/node:24-alpine3.22-dev como imagen base.
# ========================================
# Dockerfile multi-etapa optimizado
# Aplicación Node.js TypeScript (usando DHI)
# ========================================
FROM dhi.io/node:24-alpine3.22-dev AS base
# Establecer el directorio de trabajo
WORKDIR /app
# Crear un usuario no root por seguridad
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs && \
chown -R nodejs:nodejs /app
# ========================================
# Etapa de dependencias
# ========================================
FROM base AS deps
# Copiar archivos de paquete
COPY package*.json ./
# Instalar dependencias de producción
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci --omit=dev && \
npm cache clean --force
# Establecer la propiedad adecuada
RUN chown -R nodejs:nodejs /app
# ========================================
# Etapa de dependencias de construcción
# ========================================
FROM base AS build-deps
# Copiar archivos de paquete
COPY package*.json ./
# Instalar todas las dependencias con optimizaciones de construcción
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci --no-audit --no-fund && \
npm cache clean --force
# Crear los directorios necesarios y establecer permisos
RUN mkdir -p /app/node_modules/.vite && \
chown -R nodejs:nodejs /app
# ========================================
# Etapa de construcción
# ========================================
FROM build-deps AS build
# Copiar solo los archivos necesarios para la construcción (respeta .dockerignore)
COPY --chown=nodejs:nodejs . .
# Construir la aplicación
RUN npm run build
# Establecer la propiedad adecuada
RUN chown -R nodejs:nodejs /app
# ========================================
# Etapa de desarrollo
# ========================================
FROM build-deps AS development
# Establecer el entorno
ENV NODE_ENV=development \
NPM_CONFIG_LOGLEVEL=warn
# Copiar archivos fuente
COPY . .
# Asegurar que todos los directorios tengan los permisos adecuados
RUN mkdir -p /app/node_modules/.vite && \
chown -R nodejs:nodejs /app && \
chmod -R 755 /app
# Cambiar a usuario no root
USER nodejs
# Exponer puertos
EXPOSE 3000 5173 9229
# Iniciar el servidor de desarrollo
CMD ["npm", "run", "dev:docker"]
# ========================================
# Etapa de producción
# ========================================
FROM dhi.io/node:24-alpine3.22-dev AS production
# Establecer el directorio de trabajo
WORKDIR /app
# Crear un usuario no root por seguridad
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs && \
chown -R nodejs:nodejs /app
# Establecer variables de entorno optimizadas
ENV NODE_ENV=production \
NODE_OPTIONS="--max-old-space-size=256 --no-warnings" \
NPM_CONFIG_LOGLEVEL=silent
# Copiar las dependencias de producción desde la etapa deps
COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=deps --chown=nodejs:nodejs /app/package*.json ./
# Copiar la aplicación construida desde la etapa build
COPY --from=build --chown=nodejs:nodejs /app/dist ./dist
# Cambiar a usuario no root por seguridad
USER nodejs
# Exponer puerto
EXPOSE 3000
# Iniciar el servidor de producción
CMD ["node", "dist/server.js"]
# ========================================
# Etapa de pruebas
# ========================================
FROM build-deps AS test
# Establecer el entorno
ENV NODE_ENV=test \
CI=true
# Copiar archivos fuente
COPY --chown=nodejs:nodejs . .
# Cambiar a usuario no root
USER nodejs
# Ejecutar pruebas con cobertura
CMD ["npm", "run", "test:coverage"]Ahora necesitas crear un Dockerfile multi-etapa listo para producción. Reemplaza el Dockerfile generado por la siguiente configuración optimizada:
# ========================================
# Dockerfile multi-etapa optimizado
# Aplicación Node.js TypeScript
# ========================================
ARG NODE_VERSION=24.11.1-alpine
FROM node:${NODE_VERSION} AS base
# Establecer el directorio de trabajo
WORKDIR /app
# Crear un usuario no root por seguridad
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs && \
chown -R nodejs:nodejs /app
# ========================================
# Etapa de dependencias
# ========================================
FROM base AS deps
# Copiar archivos de paquete
COPY package*.json ./
# Instalar dependencias de producción
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci --omit=dev && \
npm cache clean --force
# Establecer la propiedad adecuada
RUN chown -R nodejs:nodejs /app
# ========================================
# Etapa de dependencias de construcción
# ========================================
FROM base AS build-deps
# Copiar archivos de paquete
COPY package*.json ./
# Instalar todas las dependencias con optimizaciones de construcción
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci --no-audit --no-fund && \
npm cache clean --force
# Crear los directorios necesarios y establecer permisos
RUN mkdir -p /app/node_modules/.vite && \
chown -R nodejs:nodejs /app
# ========================================
# Etapa de construcción
# ========================================
FROM build-deps AS build
# Copiar solo los archivos necesarios para la construcción (respeta .dockerignore)
COPY --chown=nodejs:nodejs . .
# Construir la aplicación
RUN npm run build
# Establecer la propiedad adecuada
RUN chown -R nodejs:nodejs /app
# ========================================
# Etapa de desarrollo
# ========================================
FROM build-deps AS development
# Establecer el entorno
ENV NODE_ENV=development \
NPM_CONFIG_LOGLEVEL=warn
# Copiar archivos fuente
COPY . .
# Asegurar que todos los directorios tengan los permisos adecuados
RUN mkdir -p /app/node_modules/.vite && \
chown -R nodejs:nodejs /app && \
chmod -R 755 /app
# Cambiar a usuario no root
USER nodejs
# Exponer puertos
EXPOSE 3000 5173 9229
# Iniciar el servidor de desarrollo
CMD ["npm", "run", "dev:docker"]
# ========================================
# Etapa de producción
# ========================================
ARG NODE_VERSION=24.11.1-alpine
FROM node:${NODE_VERSION} AS production
# Establecer el directorio de trabajo
WORKDIR /app
# Crear un usuario no root por seguridad
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 -G nodejs && \
chown -R nodejs:nodejs /app
# Establecer variables de entorno optimizadas
ENV NODE_ENV=production \
NODE_OPTIONS="--max-old-space-size=256 --no-warnings" \
NPM_CONFIG_LOGLEVEL=silent
# Copiar las dependencias de producción desde la etapa deps
COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=deps --chown=nodejs:nodejs /app/package*.json ./
# Copiar la aplicación construida desde la etapa build
COPY --from=build --chown=nodejs:nodejs /app/dist ./dist
# Cambiar a usuario no root por seguridad
USER nodejs
# Exponer puerto
EXPOSE 3000
# Iniciar el servidor de producción
CMD ["node", "dist/server.js"]
# ========================================
# Etapa de pruebas
# ========================================
FROM build-deps AS test
# Establecer el entorno
ENV NODE_ENV=test \
CI=true
# Copiar archivos fuente
COPY --chown=nodejs:nodejs . .
# Cambiar a usuario no root
USER nodejs
# Ejecutar pruebas con cobertura
CMD ["npm", "run", "test:coverage"]Características clave de este Dockerfile:
- Estructura multi-etapa — Etapas separadas para dependencias, construcción, desarrollo, producción y pruebas para mantener cada fase limpia y eficiente.
- Imagen de producción ligera — La superposición de capas optimizada reduce el tamaño y conserva únicamente lo requerido para ejecutar la aplicación.
- Configuración centrada en la seguridad — Utiliza un usuario dedicado no root y excluye paquetes innecesarios.
- Diseño enfocado al rendimiento — Uso eficaz de la caché y capas bien estructuradas para construcciones más rápidas.
- Entorno de ejecución limpio — Elimina archivos innecesarios en producción, como documentación, pruebas y cachés de construcción.
- Uso directo de puertos — La aplicación se ejecuta internamente en el puerto 3000, expuesto externamente como puerto 8080.
- Tiempo de ejecución optimizado en memoria — Node.js está configurado para ejecutarse con un límite de memoria más pequeño que el predeterminado.
Paso 2: Configura el archivo .dockerignore
El archivo .dockerignore le indica a Docker qué archivos y carpetas excluir al construir la imagen.
NoteEsto ayuda a:
- Reducir el tamaño de la imagen.
- Acelerar el proceso de construcción.
- Evitar que archivos confidenciales o innecesarios (como
.env,.gitonode_modules) se agreguen a la imagen final.Para conocer más, visita la referencia de .dockerignore.
Copia y reemplaza el contenido de tu .dockerignore existente con la configuración optimizada:
# .dockerignore optimizado para la aplicación de tareas (Todo) en Node.js + React
# Basado en la estructura real del proyecto
# Control de versiones
.git/
.github/
.gitignore
# Dependencias (instaladas en el contenedor)
node_modules/
# Salidas de construcción (construidas en el contenedor)
dist/
# Archivos de entorno
.env*
# Archivos de desarrollo
.vscode/
*.log
coverage/
.eslintcache
# Archivos del sistema operativo
.DS_Store
Thumbs.db
# Documentación
*.md
docs/
# Configuraciones de despliegue
compose.yml
Taskfile.yml
nodejs-sample-kubernetes.yaml
# Configuraciones no esenciales (mantener configuraciones de construcción)
*.config.js
!vite.config.ts
!esbuild.config.js
!tailwind.config.js
!postcss.config.js
!tsconfig.jsonPaso 3: Construye la imagen de la aplicación Node.js
Después de crear todos los archivos de configuración, el directorio de tu proyecto debería contener todos los archivos de configuración de Docker necesarios:
├── docker-nodejs-sample/
│ ├── Dockerfile
│ ├── .dockerignore
│ ├── compose.yml
│ └── README.Docker.mdAhora puedes construir la imagen de Docker para tu aplicación Node.js.
NoteEl comando
docker buildempaqueta tu aplicación en una imagen utilizando las instrucciones del Dockerfile. Incluye todos los archivos necesarios del directorio actual (denominado contexto de construcción).
Ejecuta el siguiente comando desde la raíz de tu proyecto:
$ docker build --target production --tag docker-nodejs-sample .
Qué hace este comando:
- Utiliza el Dockerfile en el directorio actual (
.). - Apunta a la etapa de producción (
production) de la construcción multi-etapa. - Empaqueta la aplicación y sus dependencias en una imagen de Docker.
- Etiqueta la imagen como
docker-nodejs-samplepara que puedas hacer referencia a ella más adelante.
Paso 4: Visualiza las imágenes locales
Después de construir tu imagen de Docker, puedes verificar qué imágenes están disponibles en tu máquina local usando la CLI de Docker o Docker Desktop. Dado que ya estás trabajando en la terminal, utiliza la CLI de Docker.
Para listar todas las imágenes de Docker disponibles localmente, ejecuta el siguiente comando:
$ docker images
Salida de ejemplo:
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-nodejs-sample latest 423525528038 14 seconds ago 237.46MBEsta salida proporciona detalles clave sobre tus imágenes:
- Repository – El nombre asignado a la imagen.
- Tag – Una etiqueta de versión que ayuda a identificar diferentes construcciones (por ejemplo,
latest). - Image ID – Un identificador único para la imagen.
- Created – La marca de tiempo que indica cuándo se construyó la imagen.
- Size – El espacio total en disco utilizado por la imagen.
Si la construcción fue exitosa, deberías ver la imagen docker-nodejs-sample en la lista.
Ejecuta la aplicación contenerizada
En el paso anterior, creaste un Dockerfile para tu aplicación Node.js y construiste una imagen de Docker utilizando el comando docker build. Ahora es el momento de ejecutar esa imagen en un contenedor y verificar que tu aplicación funcione como se espera.
Dentro del directorio docker-nodejs-sample, ejecuta el siguiente comando en una terminal:
$ docker compose up app-dev --build
La aplicación de desarrollo se iniciará con ambos servidores:
- Servidor API: http://localhost:3000 - Backend de Express.js con API REST
- Frontend: http://localhost:5173 - Servidor de desarrollo de Vite con frontend de React
- Comprobación de estado (Health Check): http://localhost:3000/health - Estado de salud de la aplicación
Para un despliegue de producción, puedes utilizar:
$ docker compose up app-prod --build
Lo cual sirve la aplicación full-stack en http://localhost:8080 con el servidor Express ejecutándose internamente en el puerto 3000, mapeado externamente al puerto 8080.
Deberías ver una aplicación moderna de lista de tareas (Todo List) con React 19 y una API REST completamente funcional.
Presiona CTRL + C en la terminal para detener la aplicación.
Ejecuta la aplicación en segundo plano
Puedes ejecutar la aplicación desconectada de la terminal (detached mode) agregando la opción -d. Dentro del directorio docker-nodejs-sample, ejecuta el siguiente comando en una terminal:
$ docker compose up app-dev --build -d
Abre un navegador y visualiza la aplicación en http://localhost:3000 (API) o http://localhost:5173 (frontend). Deberías ver la aplicación de tareas ejecutándose.
Para confirmar que el contenedor se está ejecutando, utiliza el comando docker ps:
$ docker ps
Esto listará todos los contenedores activos junto con sus puertos, nombres y estado. Busca un contenedor que exponga los puertos 3000, 5173 y 9229 para la aplicación de desarrollo.
Salida de ejemplo:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
93f3faee32c3 docker-nodejs-sample-app-dev "docker-entrypoint.s…" 33 seconds ago Up 31 seconds 0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp, 0.0.0.0:5173->5173/tcp, [::]:5173->5173/tcp, 0.0.0.0:9230->9229/tcp, [::]:9230->9229/tcp todoapp-devEjecuta diferentes perfiles
Puedes ejecutar diferentes configuraciones utilizando los perfiles de Docker Compose:
# Ejecutar producción
$ docker compose up app-prod -d
# Ejecutar pruebas
$ docker compose up app-test -d
Para detener la aplicación, ejecuta:
$ docker compose down
NotePara obtener más información sobre los comandos de Compose, consulta la referencia de la CLI de Compose.
Resumen
En esta guía, aprendiste a contenerizar, construir y ejecutar una aplicación Node.js utilizando Docker. Siguiendo las mejores prácticas, creaste una configuración segura, optimizada y lista para producción.
Lo que lograste:
- Inicializaste tu proyecto usando
docker initpara estructurar los archivos de configuración esenciales de Docker. - Creaste un archivo
compose.ymlcon servicios de desarrollo, producción y base de datos. - Estableciste la configuración del entorno con un archivo
.envpara ajustes de despliegue flexibles. - Reemplazaste el
Dockerfilepredeterminado por una construcción multi-etapa optimizada para TypeScript y React. - Reemplazaste el archivo
.dockerignorepredeterminado para excluir archivos innecesarios y mantener la imagen limpia y eficiente. - Construiste tu imagen de Docker usando
docker build. - Ejecutaste el contenedor usando
docker compose up, tanto en primer plano como en segundo plano (detached mode). - Verificaste que la aplicación se estuviera ejecutando visitando http://localhost:8080 (producción) o http://localhost:3000 (desarrollo).
- Aprendiste a detener la aplicación contenerizada usando
docker compose down.
Ahora tienes una aplicación Node.js completamente contenerizada, ejecutándose en un contenedor Docker y lista para ser desplegada en cualquier entorno con confianza y consistencia.
Recursos relacionados
Explora referencias oficiales y mejores prácticas para perfeccionar tu flujo de trabajo con Docker:
- Construcciones multi-etapa – Aprende a separar las etapas de construcción y de ejecución.
- Mejores prácticas para escribir Dockerfiles – Escribe Dockerfiles eficientes, fáciles de mantener y seguros.
- Contexto de construcción en Docker – Conoce cómo afecta el contexto a las construcciones de imágenes.
- Referencia de CLI de
docker init– Genera automáticamente assets de Docker. - Referencia de CLI de
docker build– Construye imágenes de Docker a partir de un Dockerfile. - Referencia de CLI de
docker images– Gestiona e inspecciona imágenes de Docker locales. - Referencia de CLI de
docker compose up– Inicia y ejecuta aplicaciones multi-contenedor. - Referencia de CLI de
docker compose down– Detiene y elimina contenedores, redes y volúmenes.
Próximos pasos
Con tu aplicación Node.js ahora contenerizada, estás listo para avanzar al siguiente paso.
En la siguiente sección, aprenderás cómo desarrollar tu aplicación utilizando contenedores Docker, lo que te permitirá contar con un entorno de desarrollo consistente, aislado y reproducible en cualquier máquina.