Guía de despliegue

Centralizar sus logs Docker en un VPS con Loki y Grafana

Desplegar en un VPS Cloud →

Tutorial

Centralizar sus logs Docker en un VPS con Loki y Grafana

Seguridad y monitorización11 min de lectura9 pasos

Ir saltando de SSH en SSH para leer los logs de cada contenedor cuesta tiempo — el que hace falta para localizar un error 502 que se produjo en varios servicios a la vez. Loki resuelve este problema centralizando todos sus flujos de logs en un único panel de Grafana, con un consumo de memoria compatible con un VPS estándar, allí donde una stack ELK exigiría un servidor dedicado. Esta guía cubre el despliegue completo: Loki, Promtail, Grafana y la configuración posterior a la instalación.

Contenido· Por qué centralizar sus logs en un VPS en lugar de seguir con SSH1/10
  1. 01Por qué centralizar sus logs en un VPS en lugar de seguir con SSH
  2. 02Lo que esta stack aporta en concreto
  3. 03Requisitos previos antes de desplegar
  4. 04Despliegue paso a paso
  5. 05Configuración posterior a la instalación: retención, copia de seguridad y alertas
  6. 06Solución de problemas: errores frecuentes y su resolución
  7. 07Errores frecuentes
  8. 08Un panel para correlacionar logs y métricas
  9. 09Loki frente a ELK y a los logs por SSH: qué enfoque para cada caso
  10. 10Lo que acaba de poner en órbita

Por qué centralizar sus logs en un VPS en lugar de seguir con SSH

Cuando un error afecta a varios servicios de forma simultánea — un timeout del lado de la aplicación, un 502 del lado de nginx, una excepción en un worker — ninguna herramienta SSH permite correlacionar esos eventos sin leerlos uno por uno. docker compose logs -f app, luego docker compose logs -f nginx, luego docker compose logs -f worker: es el diagnóstico en serie, sobre un solo servidor. Con dos VPS, la duración se duplica. Con tres, se triplica.

Loki es un sistema de agregación de logs de código abierto desarrollado por Grafana Labs y listado en el catálogo de la CNCF. A diferencia de Elasticsearch, que indexa la totalidad del contenido de cada línea, Loki solo indexa los labels — metadatos ligeros como el nombre del contenedor, el nombre del servicio o el entorno. Los logs en sí se comprimen y se almacenan tal cual. Esta decisión de diseño tiene una consecuencia directa: Loki funciona con holgura en un VPS de 2 GB de RAM, allí donde una stack ELK básica exige al menos entre 8 y 16 GB para mantenerse estable. Para un desarrollador o un sysadmin que gestiona varias aplicaciones autoalojadas sin presupuesto de APM enterprise, esa es la diferencia entre una solución viable y una solución poco realista.

Lo que esta stack aporta en concreto

  • Búsqueda unificada en todos los contenedores — una sola consulta LogQL cubre el conjunto de los servicios en todos sus VPS, sin SSH ni grep distribuido.
  • Correlación temporal — Grafana muestra Loki (logs) y Prometheus (métricas) en el mismo eje de tiempo: usted ve el error 502 y el pico de CPU que lo precedió en una sola vista.
  • Sin cuota de ingesta — almacena tantos logs como se lo permita su disco, sin suscripción ni límite mensual impuesto por un tercero.
  • Huella de memoria contenida — Loki consume claramente menos RAM que Elasticsearch con un volumen de logs equivalente, gracias a la indexación únicamente por labels.
  • Retención configurable — defina la duración de conservación por label (chunk_retain_period, retention_period) según sus limitaciones de disco y de cumplimiento.
  • Integración nativa con Grafana — Loki es una fuente de datos de primera clase en Grafana: sin plugin de terceros, sin API intermedia.
  • Alertas sobre el contenido de los logs — Grafana puede lanzar una alerta cuando una expresión regular coincide en un flujo Loki, sin pasar por un servicio externo.
  • Datos alojados en su infraestructura — los logs permanecen en su VPS, sin transitar por un servicio en la nube.

Requisitos previos antes de desplegar

La stack Loki + Promtail + Grafana es ligera, pero tiene sus propias exigencias. Esto es lo que necesita antes de empezar.

Recursos VPS recomendados: 2 vCPU y 2 GB de RAM son el mínimo razonable para un uso en un solo servidor con algunas decenas de contenedores activos. Si recopila los logs de varios VPS o de un gran número de servicios, apunte a 4 GB de RAM. Loki no mantiene los logs en memoria: los comprime y los escribe en disco, lo que mantiene la huella de memoria estable en el tiempo. Prevea entre 20 y 50 GB de almacenamiento SSD según su volumen de logs y su duración de retención.

Software necesario: Docker y Docker Compose v2 instalados en el VPS, un subdominio dedicado (logs.su-dominio.com) apuntando a la IP del VPS, y los puertos 3100 (Loki) y 3000 (Grafana) accesibles internamente. El puerto 3100 no debe exponerse públicamente — Loki no tiene capa de autenticación nativa, solo Grafana se expone mediante reverse proxy.

Despliegue paso a paso

  1. Crear la estructura de directorios

    Conéctese a su VPS y cree un directorio dedicado: mkdir -p /opt/loki-stack/{loki,promtail} && cd /opt/loki-stack. Esta carpeta alojará los archivos de configuración de Loki y de Promtail, así como el docker-compose.yml.

  2. Escribir la configuración de Loki

    Cree /opt/loki-stack/loki/loki-config.yaml con el contenido siguiente:

    auth_enabled: false — desactiva la autenticación multi-tenant, suficiente para un uso en un solo VPS.

    server: { http_listen_port: 3100 }

    ingester: { lifecycler: { address: 127.0.0.1, ring: { kvstore: { store: inmemory }, replication_factor: 1 } }, chunk_idle_period: 5m, chunk_retain_period: 30s }

    schema_config: { configs: [ { from: 2020-10-24, store: boltdb-shipper, object_store: filesystem, schema: v11, index: { prefix: index_, period: 24h } } ] }

    storage_config: { boltdb_shipper: { active_index_directory: /loki/boltdb-shipper-active, cache_location: /loki/boltdb-shipper-cache, shared_store: filesystem }, filesystem: { directory: /loki/chunks } }

    limits_config: { retention_period: 720h }

  3. Escribir la configuración de Promtail

    Cree /opt/loki-stack/promtail/promtail-config.yaml. Promtail es el agente que recopila los logs de los contenedores Docker y los envía a Loki:

    server: { http_listen_port: 9080, grpc_listen_port: 0 }

    positions: { filename: /tmp/positions.yaml }

    clients: [ { url: http://loki:3100/loki/api/v1/push } ]

    scrape_configs: [ { job_name: docker, docker_sd_configs: [ { host: unix:///var/run/docker.sock, refresh_interval: 5s } ], relabel_configs: [ { source_labels: ['__meta_docker_container_name'], regex: '/(.*)', target_label: container }, { source_labels: ['__meta_docker_container_log_stream'], target_label: stream } ] } ]

    Esta configuración utiliza el descubrimiento automático de Docker (docker_sd_configs), que detecta cada contenedor arrancado sin intervención manual.

  4. Escribir el archivo docker-compose.yml

    Cree /opt/loki-stack/docker-compose.yml:

    version: '3.8'

    services:
    loki: image: grafana/loki:3.0.0 ports: ['127.0.0.1:3100:3100'] volumes: [loki-data:/loki, ./loki/loki-config.yaml:/etc/loki/local-config.yaml] command: -config.file=/etc/loki/local-config.yaml restart: unless-stopped

    promtail: image: grafana/promtail:3.0.0 volumes: [/var/run/docker.sock:/var/run/docker.sock:ro, ./promtail/promtail-config.yaml:/etc/promtail/config.yml, /var/log:/var/log:ro] command: -config.file=/etc/promtail/config.yml restart: unless-stopped depends_on: [loki]

    grafana: image: grafana/grafana:latest ports: ['127.0.0.1:3000:3000'] volumes: [grafana-data:/var/lib/grafana] environment: [GF_SECURITY_ADMIN_PASSWORD=cambie-esto] restart: unless-stopped depends_on: [loki]

    volumes: loki-data: grafana-data:

    Observe que Loki (3100) y Grafana (3000) están enlazados únicamente en 127.0.0.1 — no son directamente accesibles desde el exterior.

  5. Arrancar la stack

    Desde /opt/loki-stack, ejecute: docker compose up -d. Espere entre 20 y 30 segundos y compruebe que los tres contenedores están en ejecución: docker compose ps. Revise después los logs de Loki para confirmar que ha arrancado sin errores: docker compose logs -f loki. Debe ver una línea msg="Loki started" en la salida.

  6. Configurar el reverse proxy para Grafana

    Exponga Grafana mediante nginx con un subdominio y un certificado TLS. Cree /etc/nginx/sites-available/grafana.conf:

    server { listen 443 ssl; server_name logs.su-dominio.com; ssl_certificate /etc/letsencrypt/live/logs.su-dominio.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/logs.su-dominio.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

    Obtenga el certificado con: certbot certonly --nginx -d logs.su-dominio.com, y active después el sitio: ln -s /etc/nginx/sites-available/grafana.conf /etc/nginx/sites-enabled/ && nginx -t && systemctl reload nginx.

  7. Añadir Loki como fuente de datos en Grafana

    Abra https://logs.su-dominio.com en su navegador. Inicie sesión con el usuario admin y la contraseña que definió en GF_SECURITY_ADMIN_PASSWORD. Vaya a Connections → Data sources → Add data source, elija Loki e indique la URL: http://loki:3100. Haga clic en Save & test — debe ver el mensaje Data source connected and labels found.

  8. Consultar sus primeros logs

    En Grafana, abra la pestaña Explore y seleccione la fuente Loki. Use el Log Browser para elegir un label container y filtrar por nombre de contenedor. Por ejemplo, para ver todos los logs del contenedor nginx: {container="nginx"}. Para filtrar por una cadena: {container="nginx"} |= "error". Para contar los errores por contenedor durante la última hora: sum by (container) (count_over_time({container=~".+"} |= "error" [1h])).

  9. Recopilar los logs de un segundo VPS

    Para centralizar los logs de un segundo VPS en la misma instancia de Loki, despliegue únicamente Promtail en ese VPS secundario. En su configuración, sustituya la URL del cliente por la dirección interna de su primer VPS: url: http://<IP-del-VPS-Loki>:3100/loki/api/v1/push. Abra el puerto 3100 únicamente entre los dos VPS (firewall o red privada), nunca públicamente. Añada un label estático para distinguir los logs por servidor: static_configs: [ { labels: { host: vps2 } } ].

Configuración posterior a la instalación: retención, copia de seguridad y alertas

Una vez arrancada la stack, hay tres ajustes importantes antes de dar el despliegue por completo.

Retención. El valor retention_period: 720h de loki-config.yaml corresponde a 30 días. Ajuste este parámetro según el disco disponible (docker system df para conocer la ocupación de los volúmenes). Loki aplica la retención en segundo plano, sin impacto apreciable en el rendimiento.

Copia de seguridad. El volumen loki-data contiene los índices BoltDB y los chunks comprimidos — es el único elemento que hay que respaldar. Una instantánea diaria del volumen Docker (docker run --rm -v loki-data:/data -v /backup:/backup alpine tar czf /backup/loki-$(date +%F).tar.gz /data) basta para un uso estándar. No respalde Grafana sin su volumen grafana-data (contiene sus dashboards y sus alertas).

Alertas sobre el contenido de los logs. En Grafana, cree una alerta de tipo Grafana managed alert sobre una consulta Loki: por ejemplo, lanzar una notificación cuando el número de líneas que contienen FATAL supere 0 en los últimos 5 minutos. Configure un canal de notificación (correo electrónico, Slack, webhook) en Alerting → Contact points antes de crear la regla.

Loki no expone ningún mecanismo de autenticación nativo en el puerto 3100. Si necesita exponer la API de Loki a una red que no controla (para Promtail remotos, por ejemplo), coloque delante un reverse proxy nginx con autenticación por certificado de cliente o basic auth. Nunca deje el puerto 3100 abierto en 0.0.0.0 en un VPS en producción. Del lado de Grafana, active la autenticación estricta: GF_AUTH_ANONYMOUS_ENABLED=false y GF_USERS_ALLOW_SIGN_UP=false en las variables de entorno del contenedor.

Solución de problemas: errores frecuentes y su resolución

Estos son los problemas más habituales durante el despliegue de la stack Loki + Promtail + Grafana.

Errores frecuentes

  • msg="error creating ingester" err="context deadline exceeded" al arrancar Loki — el contenedor Loki no tiene acceso de escritura al volumen montado. Compruebe los permisos del directorio correspondiente al volumen Docker (docker inspect loki-data para encontrar la ruta real) y asegúrese de que el usuario del contenedor (UID 10001 en las imágenes Grafana recientes) puede escribir en él: chown -R 10001:10001 /ruta/al/volumen.
  • Data source connected and labels found no aparece en Grafana y se sustituye por connection refused — Grafana no consigue alcanzar Loki. Compruebe que la URL indicada en la fuente de datos sea http://loki:3100 (nombre del servicio Docker, no localhost) y que ambos contenedores estén en la misma red Docker (docker inspect loki-grafana-stack_default).
  • Promtail no recopila ningún log y docker compose logs -f promtail muestra component=discovery.docker msg="refreshing targets" en bucle sin avanzar — Promtail no tiene acceso al socket de Docker. Compruebe que el volumen /var/run/docker.sock:/var/run/docker.sock:ro esté declarado en el servicio Promtail y que el socket exista en el host: ls -la /var/run/docker.sock.
  • err="entry out of order for stream" en los logs de Loki — llegan logs con marcas de tiempo desordenadas (un contenedor reiniciado que reenvía logs antiguos, por ejemplo). Añada max_stream_label_count: 0 en limits_config y unordered_writes: true en ingester de loki-config.yaml para aceptar las entradas fuera de secuencia.
  • Grafana muestra no data en una consulta LogQL que sin embargo es válida — compruebe primero el rango de tiempo seleccionado en la parte superior derecha (la trampa más habitual: rango fijado en last 5 minutes cuando Promtail todavía no ha recopilado logs recientes). Compruebe después que el label usado en su consulta existe realmente: {container="nginx"} falla si el contenedor se llama nginx-1 — use el Log Browser para explorar los labels disponibles.

Un panel para correlacionar logs y métricas

El principal interés de Loki en un entorno Grafana ya existente es la correlación con las métricas de Prometheus. Si ya dispone de una fuente Prometheus (véase el artículo sobre la monitorización de un VPS con Grafana y Prometheus), puede crear un dashboard mixto: una fila de paneles de métricas (CPU, memoria, tasa de peticiones HTTP) arriba, y un panel de logs Loki filtrado por el mismo servicio abajo. Cuando aparece un pico de CPU a las 14:37, usted ve de inmediato qué logs se emitieron en ese instante preciso, sin cambiar de herramienta ni volver a lanzar un comando SSH. Este tipo de correlación es el caso de uso que justifica desplegar ambas stacks en lugar de una u otra: Prometheus para «lo que se mide», Loki para «lo que se cuenta».

Loki frente a ELK y a los logs por SSH: qué enfoque para cada caso

Desplace la tabla

CriterioSSH + docker logsStack ELK (Elastic)Loki + Grafana
RAM necesariaNinguna (sin servicio)8–16 GB mínimo por nodo2–4 GB para un VPS estándar
IndexaciónNingunaIndexación full-text (Elasticsearch)Indexación solo por labels
Búsqueda multiservidorImposible sin scriptSí, de forma nativaSí, con Promtail en varios hosts
Correlación con métricasManualCon Kibana + APM (complejo)Nativa en Grafana
Coste de softwareNuloLicencia Basic gratuita, funcionalidades limitadasTotalmente open source, sin cuota

Lo que acaba de poner en órbita

Ahora dispone de una stack de agregación de logs operativa: Loki almacena e indexa por labels, Promtail recopila automáticamente los flujos de todos sus contenedores Docker, y Grafana ofrece una interfaz de búsqueda y de alerta. La stack funciona íntegramente en su VPS, sin servicio de terceros, sin cuota de ingesta y sin coste de software adicional.

Los siguientes pasos naturales: conectar esta stack a su monitorización Prometheus existente para la correlación métricas/logs, activar el trazado distribuido con Tempo si sus aplicaciones emiten trazas OpenTelemetry, y explorar las alertas de Grafana sobre el contenido de los logs para recibir un aviso antes de que sus usuarios señalen un problema.

Un VPS listo para su stack de observabilidad

Despliegue Loki, Promtail y Grafana en un VPS Cloud de ServOrbit con acceso root completo, IPv4 dedicada y almacenamiento SSD. Sin restricciones de puertos, sin sobrecoste de software.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva