Docker para desarrolladores: imágenes, contenedores y Compose

DevOps2026-10-06TryQuickToolBox

Has creado una aplicación web que funciona perfectamente en tu máquina, pero cuando la implementas en un servidor o la compartes con un compañero de equipo, falla. Faltan dependencias, hay conflictos de versiones o las variables de entorno son incorrectas. Este es el clásico problema de "funciona en mi máquina". Docker lo resuelve empaquetando tu aplicación y sus dependencias en una unidad estandarizada llamada contenedor. En esta guía, aprenderás los conceptos básicos de Docker—imágenes, contenedores y Compose—y cómo usarlos para optimizar tu flujo de trabajo de desarrollo.

¿Qué es Docker?

Docker es una plataforma para construir, ejecutar y enviar aplicaciones en contenedores. Un contenedor es un paquete ejecutable ligero y autónomo que incluye todo lo necesario para ejecutar un software: código, tiempo de ejecución, herramientas del sistema, bibliotecas y configuraciones. Los contenedores aíslan las aplicaciones entre sí y de la infraestructura subyacente, garantizando la consistencia entre entornos.

Imágenes vs. Contenedores

Una imagen es una plantilla de solo lectura con instrucciones para crear un contenedor. Es como una instantánea de tu aplicación y su entorno. Un contenedor es una instancia ejecutable de una imagen. Puedes crear, iniciar, detener, mover o eliminar contenedores usando la API de Docker o la CLI.

Piensa en una imagen como una clase y en un contenedor como un objeto (instancia) de esa clase. Puedes ejecutar varios contenedores a partir de la misma imagen, cada uno aislado de los demás.

Construir una imagen con un Dockerfile

Un Dockerfile es un archivo de texto con instrucciones para construir una imagen. Aquí tienes un ejemplo simple para una aplicación Node.js:

# Use an official Node.js runtime as a parent image
FROM node:18-alpine

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the port the app runs on
EXPOSE 3000

# Define the command to run the app
CMD ["node", "server.js"]

Para construir la imagen, ejecuta:

docker build -t my-node-app .

La bandera -t etiqueta la imagen con un nombre (my-node-app). El . al final especifica el contexto de construcción (directorio actual).

Ejecutar contenedores

Una vez que tengas una imagen, puedes ejecutar un contenedor:

docker run -p 3000:3000 -d my-node-app

Esto asigna el puerto 3000 de tu host al puerto 3000 del contenedor y lo ejecuta en modo detached (-d).

Comandos comunes:

Gestionar datos con volúmenes

Los contenedores son efímeros; cuando se eliminan, sus datos se pierden. Para persistir datos, usa volúmenes. Un volumen es un directorio fuera del sistema de archivos del contenedor, gestionado por Docker.

docker run -v my_volume:/app/data my-node-app

También puedes montar un directorio del host (bind mount) para desarrollo:

docker run -v $(pwd):/app my-node-app

Docker Compose: aplicaciones multi-contenedor

Las aplicaciones del mundo real a menudo requieren múltiples servicios: un servidor web, una base de datos, una caché, etc. Docker Compose te permite definir y ejecutar aplicaciones Docker multi-contenedor usando un archivo YAML. Aquí tienes un ejemplo de docker-compose.yml para una aplicación Node.js con una base de datos PostgreSQL:

version: '3.8'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:password@db:5432/mydb
    depends_on:
      - db
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:

Ejecuta todo el stack con:

docker compose up -d

Esto construye el servicio web, descarga la imagen de Postgres, crea una red e inicia ambos contenedores. El depends_on asegura que la base de datos se inicie antes que el servicio web.

Para detener y eliminar contenedores, redes y volúmenes:

docker compose down -v

Mejores prácticas para Docker en desarrollo

Comparación: Docker vs. Máquinas virtuales

Aspecto Contenedores Docker Máquinas virtuales
Tiempo de inicio Segundos Minutos
Uso de recursos Ligero (comparte el kernel del SO) Pesado (SO completo por VM)
Aislamiento A nivel de proceso A nivel de hardware
Portabilidad Alta (se ejecuta donde sea que Docker se ejecute) Limitada por la compatibilidad del hipervisor

Preguntas frecuentes

¿Cuál es la diferencia entre una imagen y un contenedor?

Una imagen es una plantilla de solo lectura que define la aplicación y su entorno. Un contenedor es una instancia en ejecución de una imagen. Puedes crear múltiples contenedores a partir de la misma imagen.

¿Cuándo debo usar Docker Compose?

Usa Docker Compose cuando tu aplicación consta de múltiples servicios (por ejemplo, servidor web, base de datos, caché) que necesitan trabajar juntos. Simplifica la orquestación para desarrollo y pruebas.

¿Cómo persisto datos en Docker?

Usa volúmenes para persistir datos fuera del sistema de archivos del contenedor. Los volúmenes son gestionados por Docker y se pueden compartir entre contenedores. Los bind mounts también se pueden usar para montar directorios del host.

¿Listo para contenerizar tu próximo proyecto? Comienza escribiendo un Dockerfile para una aplicación simple, luego agrega servicios gradualmente con Docker Compose. Para más herramientas de desarrollo, revisa nuestro JSON Formatter para validar y embellecer tus archivos de configuración.