Introducción a Docker Compose
Docker Compose es una herramienta que permite definir y ejecutar aplicaciones con múltiples contenedores usando un archivo de texto llamado docker-compose.yml. En lugar de escribir varios comandos docker run con todas sus opciones, describes toda tu infraestructura en un solo archivo y la levantas con un comando.
¿Por qué Docker Compose?
Sección titulada «¿Por qué Docker Compose?»Sin Compose, para levantar el stack Node-RED + Mosquitto tendrías que ejecutar:
# Sin Compose — tedioso y propenso a erroresdocker network create iot-netdocker volume create mosquitto-datadocker volume create nodered-datadocker run -d --name mosquitto --network iot-net -p 1883:1883 \ -v ./mosquitto/config:/mosquitto/config \ -v mosquitto-data:/mosquitto/data eclipse-mosquitto:2.0docker run -d --name node-red --network iot-net -p 1880:1880 \ --depends-on mosquitto -v nodered-data:/data nodered/node-red:latestCon Compose, todo eso se describe una vez en un archivo y se ejecuta con:
docker compose up -dAnatomía de un docker-compose.yml
Sección titulada «Anatomía de un docker-compose.yml»# Versión del formato de Compose (opcional desde Compose v2)version: '3.8'
# ── Redes compartidas entre servicios ─────────────────────────────────────networks: iot-net: # nombre de la red (tú lo defines) driver: bridge # tipo de red (bridge es el estándar)
# ── Volúmenes persistentes ─────────────────────────────────────────────────volumes: mosquitto-data: # volumen para datos de Mosquitto nodered-data: # volumen para flujos de Node-RED
# ── Servicios (= contenedores) ─────────────────────────────────────────────services:
mosquitto: # nombre del servicio (también es el hostname en la red) image: eclipse-mosquitto:2.0 # imagen de Docker Hub container_name: mosquitto # nombre del contenedor en el sistema restart: unless-stopped # reiniciar automáticamente si falla networks: - iot-net # conectar a la red compartida ports: - "1883:1883" # host:contenedor volumes: - ./mosquitto/config:/mosquitto/config:ro # carpeta local → contenedor (solo lectura) - mosquitto-data:/mosquitto/data # volumen Docker → contenedor healthcheck: # prueba de salud test: ["CMD", "mosquitto_sub", "-t", "$$SYS/#", "-C", "1", "-W", "3"] interval: 15s timeout: 5s retries: 3
node-red: image: nodered/node-red:latest container_name: node-red restart: unless-stopped networks: - iot-net ports: - "1880:1880" depends_on: mosquitto: condition: service_healthy # espera que Mosquitto esté sano antes de iniciar volumes: - nodered-data:/dataSecciones del archivo explicadas
Sección titulada «Secciones del archivo explicadas»services
Sección titulada «services»Cada entrada bajo services define un contenedor. El nombre del servicio (ej: mosquitto) se convierte automáticamente en el hostname que otros contenedores en la misma red pueden usar para comunicarse.
services: mosquitto: ← otros contenedores pueden usar "mosquitto" como hostname node-red: ← puede conectarse a Mosquitto usando host: "mosquitto"Especifica la imagen de Docker a usar. Puede incluir una etiqueta de versión:
image: eclipse-mosquitto:2.0 # versión específica (recomendado)image: nodered/node-red:latest # siempre la última versiónimage: influxdb:2.7 # versión exactaMapea puertos del host a puertos del contenedor con el formato "host:contenedor":
ports: - "1883:1883" # el puerto 1883 del host → puerto 1883 del contenedor - "3000:3000" - "8086:8086"Los servicios que no necesitan ser accesibles desde fuera (solo entre contenedores) no necesitan exponer puertos.
volumes
Sección titulada «volumes»Dos tipos de montajes:
volumes: # Carpeta local → contenedor (bind mount) - ./mosquitto/config:/mosquitto/config:ro # :ro = solo lectura
# Volumen Docker → contenedor (volumen gestionado) - mosquitto-data:/mosquitto/dataLos bind mounts (carpeta local) son útiles para archivos de configuración que quieres editar fácilmente. Los volúmenes Docker son mejores para datos que deben persistir (bases de datos, estados de aplicación).
environment
Sección titulada «environment»Define variables de entorno dentro del contenedor:
environment: POSTGRES_DB: flowfuse POSTGRES_USER: admin POSTGRES_PASSWORD: secreto
# También puedes usar formato de lista:environment: - POSTGRES_DB=flowfuse - POSTGRES_USER=admindepends_on
Sección titulada «depends_on»Controla el orden de inicio de los servicios:
depends_on: # Forma simple — solo espera que el contenedor esté "running" - mosquitto
# Forma con condición — espera hasta que el healthcheck pase mosquitto: condition: service_healthyhealthcheck
Sección titulada «healthcheck»Define una prueba para verificar si el servicio está listo:
healthcheck: test: ["CMD", "influx", "ping"] # comando a ejecutar dentro del contenedor interval: 10s # cada cuánto ejecutar la prueba timeout: 5s # tiempo máximo de espera retries: 5 # intentos antes de marcar como unhealthyrestart
Sección titulada «restart»Política de reinicio automático:
| Valor | Comportamiento |
|---|---|
no | Nunca reinicia (por defecto) |
always | Siempre reinicia, incluso al reiniciar Docker |
unless-stopped | Reinicia siempre excepto si lo detuviste manualmente |
on-failure | Solo reinicia si el proceso salió con error |
Para servicios IoT en producción, usa unless-stopped.
Comandos esenciales de Docker Compose
Sección titulada «Comandos esenciales de Docker Compose»Todos los comandos se ejecutan desde la carpeta que contiene el docker-compose.yml:
# Iniciar todos los servicios en segundo planodocker compose up -d
# Iniciar y ver los logs en tiempo realdocker compose up
# Detener todos los servicios (los datos en volúmenes se conservan)docker compose down
# Detener y eliminar todos los volúmenes (¡borra todos los datos!)docker compose down -v
# Ver el estado de los serviciosdocker compose ps
# Ver logs de todos los serviciosdocker compose logs
# Ver logs de un servicio específico en tiempo realdocker compose logs -f node-red
# Reiniciar un servicio específicodocker compose restart mosquitto
# Ejecutar un comando dentro de un servicio en ejecucióndocker compose exec mosquitto sh
# Ver el uso de recursos de los contenedoresdocker compose top
# Detener servicios sin eliminar los contenedoresdocker compose stop
# Iniciar servicios detenidos (sin recrearlos)docker compose start
# Recrear contenedores (aplica cambios del docker-compose.yml)docker compose up -d --force-recreateVariables de entorno con archivo .env
Sección titulada «Variables de entorno con archivo .env»Para no exponer contraseñas en el docker-compose.yml, usa un archivo .env en la misma carpeta:
INFLUX_PASSWORD=mi_password_secretoINFLUX_TOKEN=mi_token_secretoGRAFANA_PASSWORD=grafana_passY en docker-compose.yml refiérelas con ${VARIABLE}:
environment: DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUX_PASSWORD} DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${INFLUX_TOKEN}Estructura de proyecto recomendada
Sección titulada «Estructura de proyecto recomendada»Para los stacks de este curso:
mi-proyecto-iot/├── docker-compose.yml ← definición de servicios├── .env ← contraseñas y tokens (NO subir a git)├── .gitignore├── mosquitto/│ └── config/│ └── mosquitto.conf ← configuración de Mosquitto└── telegraf/ └── telegraf.conf ← configuración de Telegraf (stack TIG)Próximos pasos
Sección titulada «Próximos pasos»Con Docker y Docker Compose dominados, estás listo para los tutoriales del curso:
- Tutorial Node-RED + Mosquitto — tu primer stack IoT
- Tutorial TIG Stack — monitoreo con Grafana e InfluxDB