Desplegar contenedores es solo la mitad del trabajo; la otra mitad es saber qué está ocurriendo dentro de ellos. En esta lección aprenderemos a registrar y monitorizar contenedores: cómo consultar logs con docker logs, qué logging drivers existen (json-file, syslog, journald), cómo ver métricas en tiempo real con docker stats, cómo definir healthchecks para comprobar la salud de un servicio y, a alto nivel, cómo montar una solución de monitorización con cAdvisor, Prometheus y Grafana, además de centralizar los logs. La observabilidad es imprescindible para diagnosticar problemas y mantener aplicaciones fiables en producción.
Consultar Logs con docker logs
Por defecto, Docker captura todo lo que un contenedor escribe en la salida estándar (stdout) y la salida de error (stderr).
# Ver los logs de un contenedor
docker logs mi_contenedor
# Seguir los logs en tiempo real
docker logs -f mi_contenedor
# Mostrar solo las últimas 50 líneas con marcas de tiempo
docker logs --tail 50 --timestamps mi_contenedor-f(--follow): muestra los nuevos logs según se generan, comotail -f.--tail 50: limita la salida a las últimas 50 líneas, útil en contenedores con mucho historial.--timestamps: añade la fecha y hora de cada entrada.
Buena práctica: tu aplicación debe escribir en stdout/stderr y no en ficheros internos del contenedor, para que Docker pueda gestionar los logs de forma estándar.
Logging Drivers
Docker permite redirigir los logs a distintos destinos mediante logging drivers. El driver determina dónde y cómo se almacenan.
| Driver | Destino | Caso de uso |
|---|---|---|
| json-file | Ficheros JSON en el host (por defecto) | Uso general; permite docker logs |
| local | Formato optimizado en el host | Mejor rendimiento y rotación que json-file |
| syslog | Servidor syslog | Centralización en infraestructura existente |
| journald | systemd journal | Integración con sistemas basados en systemd |
| fluentd | Fluentd / agregadores | Pipelines de logs avanzados |
| none | Descarta los logs | Contenedores donde no interesan los logs |
Configurar el driver al ejecutar un contenedor
docker run -d --name app \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx--log-driver json-file: usa el driver por defecto de forma explícita.--log-opt max-size=10m: cada fichero de log no superará los 10 MB.--log-opt max-file=3: mantiene como máximo 3 ficheros rotados, evitando que los logs llenen el disco.
Nota: con drivers como
syslogojournald, el comandodocker logspuede no estar disponible, ya que los logs se gestionan fuera de Docker.
Configurar journald
journalctl CONTAINER_NAME=app: consulta los logs del contenedor a través del journal de systemd.
Métricas en Tiempo Real con docker stats
- Muestra en tiempo real el uso de CPU, memoria, red y E/S de disco de todos los contenedores en ejecución.
--no-stream: toma una única instantánea en lugar de actualizarse continuamente, útil para scripts.
| Columna | Significado |
|---|---|
| CPU % | Porcentaje de CPU utilizado |
| MEM USAGE / LIMIT | Memoria usada frente al límite asignado |
| MEM % | Porcentaje de memoria respecto al límite |
| NET I/O | Datos enviados/recibidos por la red |
| BLOCK I/O | Lectura/escritura en disco |
| PIDS | Número de procesos del contenedor |
Healthchecks
Un healthcheck le indica a Docker cómo comprobar si la aplicación dentro del contenedor está realmente funcionando, no solo si el proceso está vivo.
FROM nginx:alpine
HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=10s \
CMD curl -f http://localhost/ || exit 1--interval=30s: ejecuta la comprobación cada 30 segundos.--timeout=3s: si la comprobación tarda más de 3 segundos, se considera fallida.--retries=3: tras 3 fallos consecutivos, el contenedor se marca comounhealthy.--start-period=10s: periodo de gracia inicial mientras la aplicación arranca; los fallos durante este tiempo no cuentan.CMD curl -f http://localhost/ || exit 1: la comprobación en sí;-fhace quecurldevuelva error ante respuestas HTTP de fallo.
También se puede definir al ejecutar el contenedor:
docker run -d --name web \
--health-cmd "curl -f http://localhost/ || exit 1" \
--health-interval 30s \
nginxPara ver el estado de salud:
docker ps: la columna STATUS mostrará(healthy)o(unhealthy).docker inspect --format '{{.State.Health.Status}}': extrae directamente el estado de salud.
Introducción a la Monitorización: cAdvisor, Prometheus y Grafana
Para entornos reales, los comandos puntuales no bastan: necesitas métricas históricas, alertas y paneles. Una combinación muy extendida es cAdvisor + Prometheus + Grafana.
- cAdvisor (Container Advisor): recoge métricas de uso de recursos de cada contenedor y las expone en un formato que Prometheus puede leer.
- Prometheus: base de datos de series temporales que recopila (scrapes) métricas periódicamente y permite consultarlas y definir alertas.
- Grafana: herramienta de visualización que crea paneles (dashboards) a partir de los datos de Prometheus.
version: "3.8"
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"cadvisor: monta directorios del host en solo lectura (:ro) para leer las métricas de los contenedores.prometheus: expone el puerto9090y carga su configuración desdeprometheus.yml.grafana: expone el puerto3000para acceder a los paneles desde el navegador.
Fichero de configuración de Prometheus que le indica de dónde recoger métricas:
global:
scrape_interval: 15s
scrape_configs:
- job_name: "cadvisor"
static_configs:
- targets: ["cadvisor:8080"]scrape_interval: 15s: Prometheus recoge métricas cada 15 segundos.targets: ["cadvisor:8080"]: el destino del que recopila datos; usa el nombre de servicio gracias al DNS interno de Docker.
Con esta base, en Grafana puedes importar paneles ya preparados para visualizar CPU, memoria y red por contenedor.
Centralización de Logs
En entornos con muchos contenedores y hosts, revisar logs uno a uno es inviable. La solución es centralizarlos en una plataforma común:
- Pila EFK/ELK: Elasticsearch (almacenamiento e indexación), Fluentd o Logstash (recolección y procesado) y Kibana (visualización).
- Loki + Grafana: Loki almacena logs de forma eficiente y Grafana los visualiza junto a las métricas.
- Servicios gestionados en la nube: como AWS CloudWatch Logs, Google Cloud Logging o Azure Monitor.
# Ejemplo: enviar logs a Fluentd mediante el logging driver
docker run -d --name app \
--log-driver fluentd \
--log-opt fluentd-address=localhost:24224 \
--log-opt tag=app.web \
nginx--log-driver fluentd: redirige los logs al recolector Fluentd.--log-opt fluentd-address: dirección del servidor Fluentd (datos de ejemplo).--log-opt tag=app.web: etiqueta los logs para poder filtrarlos y enrutarlos.
Errores Comunes y Consejos
- Escribir logs en ficheros internos del contenedor: rompe la gestión estándar de Docker. Escribe siempre en
stdout/stderr. - No limitar el tamaño de los logs: con
json-filesinmax-size/max-file, los logs pueden llenar el disco del host. Configura siempre la rotación. - Confundir proceso vivo con servicio sano: un proceso puede seguir ejecutándose pero no responder. Define healthchecks reales que prueben la funcionalidad.
- Olvidar el
--start-perioden healthchecks: aplicaciones que tardan en arrancar pueden marcarse comounhealthyinjustamente sin un periodo de gracia. - Monitorizar solo de forma reactiva: configura alertas en Prometheus para enterarte de los problemas antes que tus usuarios.
- Consejo: combina métricas (Prometheus/Grafana) y logs centralizados; ambos se complementan al diagnosticar incidencias.
Ejercicios
Ejercicio 1: Logs con rotación
Lanza un contenedor Nginx con el driver json-file configurado para un máximo de 5 MB por fichero y 2 ficheros. Genera tráfico y consulta los logs en tiempo real.
Ejercicio 2: Healthcheck
Crea un Dockerfile basado en Nginx con un HEALTHCHECK que compruebe la página principal. Construye la imagen, ejecútala y verifica con docker ps que aparece como healthy.
Ejercicio 3: Métricas en tiempo real
Ejecuta dos o tres contenedores y usa docker stats para identificar cuál consume más memoria. Después toma una instantánea con --no-stream de uno de ellos.
Soluciones
Solución 1
docker run -d --name web \
--log-driver json-file \
--log-opt max-size=5m \
--log-opt max-file=2 \
-p 8080:80 \
nginx
curl http://localhost:8080 # Genera alguna entrada de log
docker logs -f web # Consulta en tiempo real (Ctrl+C para salir)Solución 2
FROM nginx:alpine
RUN apk add --no-cache curl
HEALTHCHECK --interval=15s --timeout=3s --retries=3 --start-period=5s \
CMD curl -f http://localhost/ || exit 1docker build -t web_sana:1.0 .
docker run -d --name sana -p 8081:80 web_sana:1.0
sleep 20
docker ps # La columna STATUS debe mostrar (healthy)Solución 3
docker run -d --name c1 nginx
docker run -d --name c2 redis
docker run -d --name c3 postgres -e POSTGRES_PASSWORD=ejemplo
docker stats # Observa el uso de memoria de cada uno
docker stats --no-stream c3 # Instantánea única del contenedor c3Normalmente PostgreSQL consumirá más memoria que Nginx o Redis en reposo, lo que se aprecia en la columna MEM USAGE.
Conclusión
En esta lección hemos cubierto la observabilidad de contenedores: la consulta de logs con docker logs, los distintos logging drivers y su rotación, las métricas en tiempo real con docker stats, la definición de healthchecks y una introducción a la monitorización con cAdvisor, Prometheus y Grafana, junto con las estrategias de centralización de logs. Estas herramientas te permiten detectar y diagnosticar problemas antes de que afecten a tus usuarios.
Con esta lección concluimos el Módulo 5 sobre conceptos avanzados de Docker. En el Módulo 6: Docker en Producción, llevaremos todo lo aprendido al mundo real, empezando por CI/CD con Docker, donde integraremos la construcción, prueba y despliegue de imágenes en pipelines automatizados.
Docker: De Principiante a Avanzado
Módulo 1: Introducción a Docker
- ¿Qué es Docker?
- Instalando Docker
- Arquitectura de Docker
- Comandos Básicos de Docker
- Entendiendo las Imágenes de Docker
- Creando tu Primer Contenedor Docker
Módulo 2: Trabajando con Imágenes Docker
- Docker Hub y Repositorios
- Construyendo Imágenes Docker
- Conceptos Básicos de Dockerfile
- Gestionando Imágenes Docker
- Etiquetado y Publicación de Imágenes
Módulo 3: Contenedores Docker
- Ejecutando Contenedores
- Ciclo de Vida del Contenedor
- Gestionando Contenedores
- Redes en Docker
- Persistencia de Datos con Volúmenes
Módulo 4: Docker Compose
- Introducción a Docker Compose
- Definiendo Servicios en Docker Compose
- Comandos de Docker Compose
- Aplicaciones Multi-Contenedor
- Variables de Entorno en Docker Compose
Módulo 5: Conceptos Avanzados de Docker
- Profundización en Redes Docker
- Opciones de Almacenamiento Docker
- Mejores Prácticas de Seguridad en Docker
- Optimizando Imágenes Docker
- Registro y Monitoreo en Docker
Módulo 6: Docker en Producción
- CI/CD con Docker
- Orquestando Contenedores con Docker Swarm
- Introducción a Kubernetes
- Desplegando Contenedores Docker en Kubernetes
- Escalado y Balanceo de Carga
