certmundo.
es‑mx

6 min de lectura

¿Cómo orquestar múltiples contenedores con Docker Compose?

Docker Compose te permite definir y levantar múltiples contenedores con un solo comando usando un archivo YAML.

El problema de manejar todo a mano

Imagina que trabajas en el equipo de tecnología de Liverpool. Tienes una aplicación web, una base de datos PostgreSQL y un servidor de caché Redis. Sin Docker Compose, tendrías que levantar cada contenedor por separado, crear la red manualmente y escribir docenas de flags en la terminal. Si alguien nuevo entra al equipo, tendría que repetir ese proceso completo. Un solo error y nada funciona.

Eso era la realidad antes de Docker Compose. Ahora existe una mejor forma.

El sistema YAML de orquestación local

Docker Compose usa un archivo llamado docker-compose.yml. En ese archivo describes todos tus servicios, redes y volúmenes. Docker los levanta todos juntos con un comando.

Piensa en el archivo como una receta de cocina. La receta lista los ingredientes y los pasos. Cualquiera que tenga la receta puede preparar el mismo platillo exacto. Tu docker-compose.yml es esa receta para tu entorno de desarrollo.

Este sistema tiene un nombre concreto: la arquitectura de servicios declarativa. Declaras qué quieres. Docker Compose se encarga del cómo.

Anatomía de un archivo docker-compose.yml

Veamos la estructura básica:

version: "3.9"

services:
  app:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://usuario:clave@db:5432/tienda
      - REDIS_URL=redis://cache:6379
    depends_on:
      - db
      - cache
    networks:
      - red_interna

  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=usuario
      - POSTGRES_PASSWORD=clave
      - POSTGRES_DB=tienda
    volumes:
      - datos_db:/var/lib/postgresql/data
    networks:
      - red_interna

  cache:
    image: redis:7
    networks:
      - red_interna

volumes:
  datos_db:

networks:
  red_interna:

Este archivo define tres servicios: tu aplicación, la base de datos y Redis. Todos comparten la misma red red_interna. Nadie expone puertos innecesarios hacia el exterior.

Los tres comandos que usarás todos los días

Con tu archivo listo, solo necesitas tres comandos.

Levantar todo el entorno:

docker compose up -d

El flag -d corre los contenedores en segundo plano. Tu terminal queda libre.

Ver los logs de todos los servicios:

docker compose logs -f

El flag -f sigue los logs en tiempo real. Muy útil para depurar errores al inicio.

Apagar y limpiar todo:

docker compose down

Este comando detiene y elimina los contenedores. Los volúmenes se conservan a menos que agregues --volumes.

Ejemplo real: sistema de pedidos estilo FEMSA

Supón que estás construyendo un sistema de pedidos para una cadena de tiendas como las de FEMSA. Necesitas tres piezas: una API en Python, una base de datos para guardar pedidos y Redis para guardar sesiones de usuarios.

Tu archivo quedaría así:

version: "3.9"

services:
  api_pedidos:
    build: ./api
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=base_datos
      - DB_PORT=5432
      - DB_NAME=pedidos
      - DB_USER=admin
      - DB_PASSWORD=secreto123
      - REDIS_HOST=sesiones
    depends_on:
      - base_datos
      - sesiones
    networks:
      - red_app

  base_datos:
    image: postgres:15
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secreto123
      - POSTGRES_DB=pedidos
    volumes:
      - volumen_pedidos:/var/lib/postgresql/data
    networks:
      - red_app

  sesiones:
    image: redis:7-alpine
    networks:
      - red_app

volumes:
  volumen_pedidos:

networks:
  red_app:

Con este archivo, un desarrollador nuevo en el equipo solo necesita clonar el repositorio y ejecutar docker compose up -d. En menos de dos minutos tiene el entorno completo corriendo en su máquina. No importa si usa Windows, Mac o Linux.

La clave de depends_on

La directiva depends_on le dice a Docker Compose el orden en que debe iniciar los servicios. En el ejemplo anterior, api_pedidos espera a que base_datos y sesiones estén listos antes de arrancar.

Ojo: depends_on espera que el contenedor inicie, no que el servicio esté listo. PostgreSQL puede tardar unos segundos en aceptar conexiones después de que el contenedor arranca. Para eso existen healthchecks, que veremos más adelante.

Una solución práctica es que tu aplicación intente reconectarse automáticamente si falla al inicio. La mayoría de los frameworks modernos tienen esta opción.

Variables de entorno con archivo .env

Escribir contraseñas directamente en el docker-compose.yml es un error de seguridad. Si subes ese archivo a GitHub, cualquiera puede ver tus credenciales.

La solución es usar un archivo .env:

# archivo .env
DB_USER=admin
DB_PASSWORD=secreto123
DB_NAME=pedidos

Luego tu docker-compose.yml referencia esas variables así:

environment:
  - POSTGRES_USER=${DB_USER}
  - POSTGRES_PASSWORD=${DB_PASSWORD}
  - POSTGRES_DB=${DB_NAME}

Agrega .env a tu .gitignore y comparte solo .env.example con los valores vacíos. Tu equipo sabrá qué variables necesita sin exponer datos reales.

Errores comunes al usar Docker Compose

Error 1: El orden de indentación en YAML YAML es muy estricto con los espacios. Un tabulador en lugar de dos espacios rompe todo el archivo. Usa siempre dos espacios para indentar. Muchos editores como VS Code tienen plugins para validar YAML automáticamente.

Error 2: Olvidar el volumen para la base de datos Si no defines un volumen para PostgreSQL o MySQL, todos tus datos se pierden cuando haces docker compose down. Siempre declara un volumen nombrado para persistir datos. En el ejemplo de FEMSA usamos volumen_pedidos exactamente por esto.

Error 3: Publicar puertos de la base de datos No agregues ports a tu servicio de base de datos. La comunicación entre api_pedidos y base_datos ocurre dentro de la red red_app. Publicar el puerto 5432 hacia tu máquina es un riesgo de seguridad innecesario en producción.

Error 4: Usar latest como tag de imagen Escribir image: postgres:latest puede romperte el entorno cuando Postgres lance una nueva versión mayor. Siempre fija la versión: image: postgres:15. Así todos en el equipo usan exactamente la misma versión.

Error 5: No revisar los logs cuando algo falla Cuando un servicio no arranca, el instinto es editar el archivo y volver a intentar. Pero primero revisa los logs con docker compose logs nombre_del_servicio. El mensaje de error casi siempre te dice exactamente qué está mal.

Comparación: sin Compose vs. con Compose

Tarea Sin Docker Compose Con Docker Compose
Levantar 3 servicios 3 comandos largos con flags docker compose up -d
Compartir el entorno Documentación manual Un solo archivo YAML
Variables de entorno Copiar y pegar en cada comando Archivo .env centralizado
Apagar todo docker stop uno por uno docker compose down
Ver logs docker logs por servicio docker compose logs -f

La diferencia en productividad es enorme. Un equipo como el de Mercado Libre México que trabaja con decenas de microservicios no podría operar sin orquestación.

Cómo aplicar esto en tu proyecto hoy

Sigue estos pasos en orden:

  1. Crea un archivo docker-compose.yml en la raíz de tu proyecto.
  2. Define cada servicio que necesitas: app, base de datos, caché.
  3. Crea un archivo .env con tus credenciales reales.
  4. Agrega .env a tu .gitignore.
  5. Ejecuta docker compose up -d y revisa los logs con docker compose logs -f.
  6. Verifica que tu aplicación responde en el puerto que configuraste.

Empezar con un entorno sencillo de dos servicios es suficiente. Agrega Redis o cualquier otro servicio cuando lo necesites.

Docker Compose convierte un proceso de configuración repetitivo y frágil en un archivo reproducible que cualquier persona de tu equipo puede usar en minutos.

Puntos clave

  • El archivo `docker-compose.yml` describe todos tus servicios, redes y volúmenes en un solo lugar. Cualquier persona puede levantar el entorno completo con `docker compose up -d`.
  • Usa `depends_on` para controlar el orden de inicio de tus servicios. Recuerda que solo garantiza que el contenedor inicia, no que el servicio interno esté listo para recibir conexiones.
  • Guarda tus credenciales en un archivo `.env` y referencíalas en el YAML con `${VARIABLE}`. Nunca subas contraseñas reales a tu repositorio de código.
  • Siempre define volúmenes nombrados para tus bases de datos. Sin ellos, tus datos desaparecen cada vez que ejecutas `docker compose down`.
  • Fija siempre la versión de tus imágenes (por ejemplo, `postgres:15` en lugar de `postgres:latest`) para evitar que una actualización automática rompa tu entorno de trabajo.

Comparte esta lección: