Logs y observabilidad en Docker | Nicolás Garzón
logs, métricas, traces y eventos
Texto
Copiar ¿Qué ocurrió?
¿Dónde ocurrió?
¿Por qué ocurrió?
¿Desde qué cambio comenzó?docker logs es una herramienta de diagnóstico local, no una plataforma completa de observabilidad. En producción, la información debe salir del contenedor, conservarse fuera del host cuando el riesgo lo exige y correlacionarse con service, versión, digest y request.
Eventos discretos con contexto:
JSON
Copiar {
"timestamp" : "2026-07-25T05:00:00.000Z" ,
"level" : "error" ,
"service" : "api" ,
"version" : "1.8.2" ,
"requestId" : "req_01" ,
"message" : "Database query timed out" ,
"durationMs" : 5000
} Valores agregables en el tiempo:
request rate;
error rate;
p50, p95 y p99;
CPU y throttling;
memory, RSS y OOM;
queue depth;
restarts;
disk e inodes;
health state.
Relacionan una operación a través de proxy, API, worker, database y proveedores externos.
Texto
Copiar request
→ proxy span
→ API span
→ PostgreSQL span
→ payment provider spanCambios de lifecycle del Engine:
Bash
Copiar docker events --since 30m
create/start/stop/die;
OOM;
health status;
network connect/disconnect;
image pull;
volume operations.
Una aplicación debe escribir logs de proceso en stdout y stderr.
JavaScript
Copiar console. log ( JSON . stringify ( { level : 'info' , message : 'Server started' } ) ) ;
console. error ( JSON . stringify ( { level : 'error' , message : 'Request failed' } ) ) ;
Docker captura ambos streams;
el logging driver puede almacenarlos o reenviarlos;
no dependes de un archivo dentro de la writable layer;
funcionan con containers read-only;
el mismo patrón se integra con Compose y orquestadores.
No significa que stdout sea almacenamiento durable. Si el host se pierde o la retención local termina, el log desaparece.
Bash
Copiar docker logs api
docker logs --follow api
docker logs --since 10m --tail 200 api
docker logs --timestamps apidocker logs lee según el logging driver configurado y sus capacidades. No asumas que todos los drivers permiten exactamente la misma experiencia local.
Bash
Copiar docker compose logs -f --tail 200 api workerEl daemon utiliza un logging driver por defecto o uno configurado por container.
Bash
Copiar docker info --format '{{.LoggingDriver}}'
docker inspect api --format '{{json .HostConfig.LogConfig}}'
guardar localmente;
enviar a syslog;
enviar a journald;
integrarse con servicios externos;
usar plugins.
La elección cambia disponibilidad, rendimiento, buffering, backpressure y experiencia de docker logs.
Un servicio que escribe continuamente puede llenar el disco del host.
Bash
Copiar docker run \
--log-opt max-size= 10m \
--log-opt max-file= 3 \
my-apiLas opciones dependen del driver. Configura y verifica la política efectiva.
Texto
Copiar log crece
→ filesystem lleno
→ database/builds fallan
→ daemon y host se degradanRotación local tampoco reemplaza centralización. Solo limita el daño y conserva una ventana corta.
Prefiere JSON o un formato estable.
timestamp UTC;
severity;
service;
environment;
version/digest;
request ID y trace ID;
operation;
duration;
status code;
error class;
retry count.
Evita depender de parsing por regex de mensajes humanos variables.
passwords;
API keys;
authorization headers;
cookies de sesión;
connection strings completas;
private keys;
documentos personales sin redacción;
environment completo;
payloads sensibles por defecto.
La observabilidad puede convertirse en la mayor copia de datos sensibles de una organización.
allowlist de campos;
redacción;
retención;
acceso;
cifrado;
eliminación;
clasificación de PII.
Un error útil conserva contexto técnico sin exponer secretos.
JSON
Copiar {
"level" : "error" ,
"errorType" : "DatabaseTimeoutError" ,
"message" : "Query exceeded timeout" ,
"requestId" : "req_01" ,
"durationMs" : 5000
} En entornos internos puede conservarse stack trace en el sistema central. En respuestas públicas no debe enviarse automáticamente.
Genera o propaga una identidad por request:
Texto
Copiar client request ID
→ proxy
→ API
→ worker/job
→ database logSi un proveedor externo devuelve su propio ID, regístralo también. Esto permite buscar una transacción completa sin depender de timestamps aproximados.
El container ID es efímero. Registra metadata durable:
service;
image digest;
semantic version;
Git commit;
build ID;
deployment ID;
host/node;
environment.
YAML
Copiar services :
api :
image : registry.example.com/api@sha256: ...
labels :
com.nicoo.service : api
com.nicoo.version : "1.8.2"
com.nicoo.commit : "abc1234" Bash
Copiar docker stats --no-stream
CPU;
memory;
network I/O;
block I/O;
PIDs.
vista puntual;
no historial;
no explica causa;
no sustituye métricas internas;
interpretación cambia con límites y cgroups.
Un container puede usar poca CPU y aun estar devolviendo errores por una dependencia externa.
requests por ruta;
tasa de errores;
latency histogram;
pool de database;
cache hit ratio;
queue length;
event loop lag;
external dependency latency;
retries y circuit breaker state.
Evita cardinalidad no controlada. No uses user ID, URL completa o request ID como label métrica.
Un healthcheck responde una condición binaria o limitada.
Texto
Copiar healthy ≠ rápido
healthy ≠ sin errores
healthy ≠ dependencias establesCombina health con SLOs y métricas.
Tracing es útil cuando una operación cruza varios servicios.
inicio/fin;
parent-child relationship;
duration;
error status;
atributos controlados.
No adjuntes payloads sensibles indiscriminadamente. Sampling debe conservar errores y operaciones lentas sin generar costes imposibles.
Bash
Copiar docker events \
--filter container = api \
--since 1hCorrelaciona un error con:
restart;
kill;
OOM;
health transition;
recreate;
network disconnect.
Los eventos también necesitan recolección externa si deben sobrevivir al host.
El container comparte recursos del host. Monitorea:
filesystem e inodes;
load average;
memory pressure;
swap;
kernel OOM;
disk latency;
network errors;
daemon health;
clock sync;
temperature/hardware cuando aplique.
Un problema que parece de un service puede ser saturación global.
Enviar logs puede fallar o bloquear.
¿el driver bloquea la aplicación?
¿bufferiza en memoria o disco?
¿qué pasa si el destino está caído?
¿cuánta información puede perderse?
¿existe rate limit?
Una aplicación no debe caer porque el collector estuvo indisponible unos segundos, pero tampoco puede acumular logs infinitos.
Stack traces multilínea pueden fragmentarse. JSON en una línea simplifica ingestión.
Texto
Copiar Error occurred
at function A
at function BJSON
Copiar { "level" : "error" , "message" : "Error occurred" , "stack" : "Error...\n at function A..." } Utiliza timestamps UTC y sincroniza el host.
Un desfase de reloj rompe:
orden de eventos;
traces;
expiración de tokens;
correlación entre nodos.
Registra timezone de negocio solo donde sea relevante; la telemetría base debe normalizarse.
Síntoma: p99 sube de 200 ms a 5 s.
dashboard muestra inicio exacto;
deployment metadata indica nuevo digest;
traces muestran espera en PostgreSQL;
métricas del pool muestran saturación;
logs registran timeouts sin secretos;
docker stats muestra CPU normal;
host disk latency está alta;
eventos confirman que no hubo restart.
Conclusión: no era CPU del container; era I/O de storage.
Bash
Copiar docker ps -a
docker inspect api --format '{{json .State}}'
docker logs --since 15m --timestamps api
docker stats --no-stream api
docker events --since 15m --filter container = api
docker system df -v Después revisa métricas y traces externos.
Los logs locales pueden desaparecer según driver y limpieza. Centraliza antes.
Puede bloquear, bufferizar o perder eventos. Prueba el comportamiento.
Serializar payloads enormes o stack traces repetidos también consume recursos.
Una métrica etiquetada por request ID vuelve inutilizable el backend.
Un token puede aparecer dentro de URL, body o error de librería.
Usa stderr básico y captura de startup.
Se pierden al recrear y rompen rootfs read-only.
No hay historial central ni correlación multi-host.
Filtra datos y aumenta costes.
No puedes identificar qué cambio introdujo el problema.
Un service healthy puede incumplir SLO.
La telemetría debe sobrevivir al container y, según riesgo, al host.
stdout/stderr son el canal, no el archivo histórico.
Logs, métricas, traces y eventos responden preguntas diferentes.
Rotación evita llenar disco; centralización conserva evidencia.
Correlaciona con service, digest, commit y request.
Observabilidad también necesita seguridad, retención y control de costes.
Comprueba lo aprendido
Diseña los campos de log para una API y un worker.
¿Por qué docker logs no es suficiente en producción?
¿Cómo distinguirías saturación de CPU de latencia de database?
¿Qué efectos puede tener la caída de un logging backend?
Diseña una política de redacción y retención.
Supply chain, SBOM y escaneo , donde la identidad y seguridad de la imagen se extienden desde source y builder hasta registry y despliegue.