Cómo centralizar logs con Grafana Loki en Docker
Índice de contenidos
- Puntos clave
- ¿Qué es Loki y en qué se diferencia de Elasticsearch?
- ¿Cómo es el docker-compose.yml de Loki?
- ¿Cómo enviar logs con el driver de Docker o Grafana Alloy?
- ¿Cómo consultar logs con LogQL en Grafana?
- ¿Cómo configurar la retención y el almacenamiento?
- Preguntas frecuentes
- ¿Loki sustituye a Elasticsearch para logs?
- ¿Por qué no debo usar Promtail en una instalación nueva?
- ¿Cuánto consume Loki en un servidor doméstico?
- Conclusión
- Fuentes
Grafana Loki es un sistema de agregación de logs de código abierto que solo indexa etiquetas y guarda el contenido comprimido, lo que abarata el almacenamiento entre diez y cien veces frente a Elasticsearch. Con Docker lo levantas con un único docker-compose.yml, envías los registros con el driver de Docker o Grafana Alloy y los consultas con LogQL en Grafana.
Cuando tienes diez o quince contenedores repartidos por el servidor, seguir sus logs con docker logs uno a uno deja de ser viable: necesitas centralizarlos en un único sitio donde buscar. Grafana Loki es la pieza pensada exactamente para eso, y con Docker la levantas con un solo docker-compose.yml. En esta guía verás qué es Loki y por qué indexa distinto a Elasticsearch, cómo arrancarlo junto a Grafana, cómo enviarle los logs con el driver de Docker o con Grafana Alloy, cómo consultarlos con LogQL y cómo controlar la retención. La misma explicación está disponible en inglés.
Puntos clave
- Grafana Loki es un sistema de agregación de logs de código abierto creado por Grafana Labs; la versión estable más reciente es Loki 3.7.3, publicada el 24 de junio de 2026, dentro de la rama 3.7.
- A diferencia de Elasticsearch, Loki solo indexa las etiquetas (metadatos) de cada flujo de logs y guarda el texto comprimido en trozos (chunks), lo que abarata el almacenamiento entre 10 y 100 veces para el mismo volumen.
- La API HTTP y la interfaz de estado escuchan en el puerto 3100, y los logs se envían por HTTP al endpoint
/loki/api/v1/push. - Promtail dejó de tener soporte el 2 de marzo de 2026: para clientes nuevos, Grafana recomienda Grafana Alloy o el driver de logging oficial de Docker, no Promtail.
- Por defecto Loki guarda los logs para siempre (
retention_period: 0s); la retención real la aplica el componente Compactor, con un mínimo configurable de 24 horas. - Cuidado con la etiqueta
:latest: fija siempre una versión concreta comografana/loki:3.7.3para saber exactamente qué desplegar y cuándo actualizar.
¿Qué es Loki y en qué se diferencia de Elasticsearch?
Loki es un sistema de agregación de logs de código abierto que Grafana Labs describe como "Prometheus, pero para logs". La comparación no es casual: comparte con Prometheus el modelo de etiquetas y la filosofía de indexar poco. Su trabajo es recibir las líneas de log de todos tus servicios, guardarlas y dejarte buscarlas después desde Grafana con un lenguaje propio, LogQL.
La diferencia decisiva frente a la pila ELK (Elasticsearch, Logstash, Kibana) está en qué se indexa. Elasticsearch construye un índice invertido de cada palabra de cada línea: eso hace las búsquedas de texto completo muy rápidas, pero el índice suele pesar tanto como los propios datos y la memoria y el disco se disparan. Loki toma el camino contrario: indexa solo un puñado de etiquetas por flujo (por ejemplo job, container_name, level) y guarda el contenido tal cual, comprimido en trozos sobre almacenamiento de objetos o disco. El resultado es que el almacenamiento sale entre 10 y 100 veces más barato para el mismo volumen de logs.
Esa decisión tiene una contrapartida que conviene entender desde el principio: las etiquetas deben ser de baja cardinalidad. Si usas como etiqueta algo que cambia constantemente, como la IP del cliente o un identificador de petición, generas miles de flujos distintos y Loki se vuelve lento. La regla es sencilla: etiqueta por origen (servicio, contenedor, entorno) y deja los valores variables dentro del texto del log, donde LogQL los filtra en tiempo de consulta.
¿Cómo es el docker-compose.yml de Loki?
Necesitas dos archivos en la misma carpeta: la configuración de Loki (loki-config.yaml) y el docker-compose.yml que arranca Loki junto a Grafana. Empieza por una configuración mínima en modo monolítico (todo el binario en un contenedor), con almacenamiento en disco y retención activada:
auth_enabled: false
server:
http_listen_port: 3100
common:
instance_addr: 127.0.0.1
path_prefix: /loki
replication_factor: 1
ring:
kvstore:
store: inmemory
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
schema_config:
configs:
- from: "2024-01-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
compactor:
working_directory: /loki/compactor
retention_enabled: true
delete_request_store: filesystem
retention_delete_delay: 2h
limits_config:
retention_period: 744h
reject_old_samples: true
reject_old_samples_max_age: 168h
Y ahora el docker-compose.yml, que fija las versiones, monta esa configuración en modo solo lectura, persiste los datos en volúmenes con nombre y publica los puertos solo en la propia máquina:
services:
loki:
image: grafana/loki:3.7.3
restart: unless-stopped
command: -config.file=/etc/loki/loki-config.yaml
volumes:
- ./loki-config.yaml:/etc/loki/loki-config.yaml:ro
- loki_data:/loki
ports:
- "127.0.0.1:3100:3100"
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3100/ready"]
interval: 15s
timeout: 5s
retries: 5
grafana:
image: grafana/grafana:12.3.0
restart: unless-stopped
depends_on:
- loki
environment:
- GF_AUTH_ANONYMOUS_ENABLED=false
volumes:
- grafana_data:/var/lib/grafana
ports:
- "127.0.0.1:3000:3000"
volumes:
loki_data:
grafana_data:
Fíjate en un par de detalles. El volumen loki_data se monta en /loki, la ruta bajo la que Loki escribe los chunks, el índice y los datos del Compactor; si quieres entender la diferencia entre un volumen con nombre y un bind mount, la explicamos en la guía sobre volúmenes y bind mounts en Docker. Publicar los puertos como 127.0.0.1:3100:3100 y 127.0.0.1:3000:3000 deja tanto Loki como Grafana accesibles solo desde la propia máquina, porque Loki no trae autenticación (auth_enabled: false): exponerlo en Internet sin un proxy delante es un riesgo. Cuando quieras publicar Grafana con HTTPS y un dominio, pon delante un proxy inverso como se explica en cómo instalar Traefik con Docker Compose.
Con los dos archivos listos, arranca la pila y comprueba el estado:
docker compose up -d
docker compose ps
curl -s http://127.0.0.1:3100/ready
Cuando curl devuelva ready, Loki está listo para recibir logs. Abre después http://127.0.0.1:3000, entra en Grafana y añade una fuente de datos de tipo Loki con la URL http://loki:3100, usando el nombre del servicio dentro de la red de Compose. El paso a paso de esa parte lo tienes en cómo instalar Grafana con Docker.
¿Cómo enviar logs con el driver de Docker o Grafana Alloy?
Loki ya está en marcha, pero todavía no recibe nada: falta el agente que recoge las líneas y las empuja al endpoint /loki/api/v1/push. Tienes dos caminos habituales.
El más directo es el driver de logging oficial de Docker, un plugin que redirige la salida estándar de cada contenedor a Loki sin ningún agente extra. Se instala una sola vez:
docker plugin install grafana/loki-docker-driver:3.7.0-amd64 \
--alias loki --grant-all-permissions
En hosts ARM64 usa el sufijo -arm64. A partir de ahí, cualquier servicio puede enviar sus logs a Loki añadiendo un bloque logging en su definición de Compose:
services:
mi-app:
image: nginx:1.29
logging:
driver: loki
options:
loki-url: "http://localhost:3100/loki/api/v1/push"
loki-external-labels: "job=docker,container={{.Name}}"
Cada línea llega a Loki etiquetada con job=docker y el nombre del contenedor, que es justo la baja cardinalidad que Loki agradece. Ten en cuenta un aviso de la propia documentación: el driver puede bloquearse si Loki deja de estar accesible, así que en producción muchos prefieren el segundo camino.
Ese segundo camino es Grafana Alloy, el recolector que sustituye a Promtail (retirado el 2 de marzo de 2026). Alloy corre como un contenedor más, lee los logs de Docker o de ficheros, les añade etiquetas y los envía a Loki, y no arrastra el problema de bloqueo del driver. Para un homelab, empieza con el driver de Docker por su sencillez y pásate a Alloy cuando quieras enrutar, filtrar o transformar los logs antes de guardarlos. Si además quieres una vista rápida de los logs en directo sin escribir consultas, un visor ligero como Dozzle complementa bien a Loki.
¿Cómo consultar logs con LogQL en Grafana?
LogQL es el lenguaje de consulta de Loki, y quien conozca PromQL lo reconocerá enseguida. Toda consulta tiene dos partes: un selector de flujo, con etiquetas entre llaves, y un filtro de línea opcional. La consulta más simple selecciona todos los logs de un origen:
{job="docker"}
{container="mi-app"} |= "error"
{job="docker"} | json | level="error"
La primera trae todos los logs con la etiqueta job=docker. La segunda añade un filtro de línea |= "error", que se queda solo con las líneas que contienen esa cadena (usa != para excluir, |~ para expresiones regulares). La tercera va un paso más allá: | json interpreta cada línea como JSON y extrae sus campos, de modo que puedes filtrar por level="error" aunque level no sea una etiqueta indexada. Ese es el reparto de trabajo de Loki: pocas etiquetas para localizar el flujo rápido, y filtros sobre el texto para el detalle.
En Grafana, escribe estas consultas en el panel Explore con Loki como fuente de datos y verás las líneas coincidentes al instante, con un histograma de frecuencia encima. LogQL también sabe generar métricas a partir de logs; por ejemplo, rate({job="docker"} |= "error" [5m]) calcula cuántos errores por segundo aparecen en los últimos cinco minutos, un número que puedes pintar en un panel o usar en una alerta.
¿Cómo configurar la retención y el almacenamiento?
Este es el punto que más sorprende a quien llega desde otras herramientas: por defecto, Loki no borra nada. Si no configuras la retención, el retention_period vale 0s y los logs viven para siempre, así que el disco crece sin freno. La retención la aplica el Compactor, el proceso que en segundo plano fusiona los muchos índices pequeños en pocos más grandes y, de paso, elimina los chunks caducados.
En el loki-config.yaml de esta guía ya está activada con tres piezas: retention_enabled: true dentro del bloque compactor (sin esto, el Compactor solo compacta, no borra), delete_request_store: filesystem para que sepa dónde anotar las solicitudes de borrado, y retention_period: 744h en limits_config, que fija una retención global de 31 días. El mínimo que Loki admite es de 24 horas, y el periodo del índice debe ser también de 24 horas para que la retención funcione.
Puedes afinar más y dar retenciones distintas por flujo mediante reglas retention_stream, por ejemplo guardar 7 días los logs ruidosos de acceso y 90 días los de auditoría. Si el disco es tu límite, la otra palanca es controlar cuánto ocupa cada contenedor en origen con las opciones de rotación de logs de Docker, algo que cubrimos en límites de recursos y logs en Docker. Y cuando el volumen crezca de verdad, Loki puede guardar los chunks en almacenamiento de objetos S3 en lugar de en disco local, sin cambiar nada del resto del flujo.
Preguntas frecuentes
¿Loki sustituye a Elasticsearch para logs?
Para la mayoría de casos self-hosted, sí, y con mucho menos coste. Loki cubre lo que de verdad necesitas a diario: centralizar los logs de todos los contenedores, buscarlos por servicio y filtrar por texto o por campos JSON. Renuncias a la búsqueda de texto completo indexada de Elasticsearch, que solo compensa si haces analítica pesada sobre años de logs. Para un homelab o un servidor con decenas de servicios, Loki gasta una fracción del disco y la memoria y se integra de forma nativa con Grafana.
¿Por qué no debo usar Promtail en una instalación nueva?
Porque Promtail dejó de tener soporte el 2 de marzo de 2026. Durante años fue el agente recomendado para enviar logs a Loki, pero Grafana lo ha reemplazado por Grafana Alloy, que hace lo mismo y además recoge métricas y trazas con la misma configuración. En una instalación nueva, usa el driver de logging de Docker para lo sencillo y Alloy para todo lo demás; deja Promtail solo si mantienes un despliegue heredado que aún no puedes migrar.
¿Cuánto consume Loki en un servidor doméstico?
Poco, siempre que respetes la baja cardinalidad de las etiquetas. En modo monolítico, con un puñado de contenedores enviando logs, Loki funciona con holgura en unos pocos cientos de megabytes de RAM, muy por debajo de lo que pide un nodo de Elasticsearch equivalente. El disco depende de la retención y del volumen: con la compresión de los chunks y una retención de 31 días, un homelab típico se mantiene en pocos gigabytes.
Conclusión
Con un docker-compose.yml, un loki-config.yaml y el driver de logging de Docker tienes todos los logs de tu servidor centralizados, buscables con LogQL desde Grafana y con una retención controlada por el Compactor. La clave está en el modelo de Loki: indexar solo etiquetas de baja cardinalidad, guardar el texto comprimido y filtrar en tiempo de consulta, que es lo que lo hace tan barato frente a Elasticsearch. A partir de aquí, conecta los cuadros de mando de Grafana, define alertas sobre la tasa de errores y, cuando el volumen lo pida, mueve el almacenamiento a S3 sin tocar el resto de la pila.
Fuentes: [1] Documentación oficial de Grafana Loki[1], [2] Imagen oficial grafana/loki en Docker Hub[2], [3] Repositorio de Grafana Loki en GitHub[3], [4] Ciclo de versiones de Grafana Loki (endoflife.date)[4].