Ya sabes qué es Docker y cómo correr un contenedor. Ahora el siguiente paso: orquestar múltiples servicios con un solo archivo. Docker Compose hace que levantar un stack completo sea tan simple como escribir docker compose up.
¿Qué es Docker Compose?
Docker Compose es una herramienta que permite definir y ejecutar aplicaciones con múltiples contenedores usando un archivo docker-compose.yml. En lugar de correr cada contenedor manualmente con docker run, describes todos los servicios, redes y volúmenes en un solo lugar y los levantas con un comando.
Instalación
En versiones modernas de Docker Desktop (Windows y Mac), Compose ya viene incluido. En Linux:
# Verificar que Compose está disponible
docker compose version
# Si no está instalado (Linux)
sudo apt-get install docker-compose-plugin
Estructura de un docker-compose.yml
El archivo YAML define los services (contenedores), volumes (persistencia de datos) y networks (comunicación entre contenedores).
version: '3.9'
services:
nombre-servicio:
image: imagen:tag # imagen de Docker Hub
build: . # O construir desde Dockerfile local
ports:
- "puerto_host:puerto_contenedor"
environment:
VARIABLE: valor
volumes:
- datos:/ruta/interna
depends_on:
- otro-servicio
volumes:
datos:
Tu primer stack: PHP + MariaDB + phpMyAdmin
Vamos a levantar un entorno de desarrollo web completo. Crea un archivo docker-compose.yml en la raíz de tu proyecto:
version: '3.9'
services:
web:
image: php:8.2-apache
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
depends_on:
- db
environment:
- APACHE_RUN_USER=www-data
db:
image: mariadb:10.11
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root1234
MYSQL_DATABASE: miapp
MYSQL_USER: dev
MYSQL_PASSWORD: dev1234
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
pma:
image: phpmyadmin:latest
ports:
- "8081:80"
environment:
PMA_HOST: db
PMA_PORT: 3306
depends_on:
- db
volumes:
db_data:
Comandos esenciales de Compose
# Levantar todos los servicios (en background)
docker compose up -d
# Ver el estado de los servicios
docker compose ps
# Ver logs en tiempo real
docker compose logs -f
# Ver logs de un servicio específico
docker compose logs -f web
# Detener todos los servicios (sin eliminar datos)
docker compose stop
# Detener Y eliminar contenedores y redes
docker compose down
# Detener, eliminar contenedores Y volúmenes (¡borra datos!)
docker compose down -v
# Reconstruir imágenes antes de levantar
docker compose up -d --build
# Ejecutar un comando en un servicio corriendo
docker compose exec web bash
down -v: Este comando elimina los volúmenes, lo que significa que perderás todos los datos de tu base de datos. Úsalo solo cuando quieras reiniciar desde cero.
Variables de entorno con archivo .env
Es mala práctica hardcodear contraseñas en el YAML. Docker Compose lee automáticamente un archivo .env en el mismo directorio:
# .env
MYSQL_ROOT_PASSWORD=supersecreto
MYSQL_DATABASE=produccion
MYSQL_USER=appuser
MYSQL_PASSWORD=p4ssw0rd_seguro
DB_PORT=3306
# docker-compose.yml — referencia variables con ${VARIABLE}
db:
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "${DB_PORT}:3306"
.env a tu .gitignore para que las credenciales no lleguen a tu repositorio. Comparte un archivo .env.example con las variables vacías.
Redes en Compose
Compose crea automáticamente una red para todos los servicios del mismo archivo. Los contenedores se comunican usando el nombre del servicio como hostname. En el ejemplo anterior, PHP se conecta a MariaDB así:
El host es db — el nombre del servicio en el YAML, no una IP ni localhost.
Conclusión
Docker Compose transforma proyectos complicados de configurar en un solo archivo versionable. Tu equipo puede clonar el repositorio, correr docker compose up -d y tener el entorno listo en minutos, sin instalar nada más. Es la base de cualquier flujo de desarrollo moderno.
El siguiente paso natural es aprender a usar Compose en staging y producción con herramientas como Docker Swarm o Kubernetes — temas que cubriremos próximamente en solutions_.