~ / blog / observabilidade
15 ago 2026 observabilidade 12 min de leitura

Montando uma Stack de Observabilidade Completa com Docker

Guia prático para subir testes automatizados, métricas e logs em containers Docker — do zero até dashboards funcionando.

GrafanaPrometheusLokiOpenTelemetryDocker

1. Introdução e arquitetura

Uma stack de observabilidade responde três perguntas: o que está acontecendo (métricas), por que (logs) e onde (traces). Neste guia montamos tudo com Docker Compose:

  • Prometheus — coleta e armazena métricas
  • Loki — agrega logs (estilo Prometheus)
  • Grafana — visualização unificada
  • OpenTelemetry Collector — recebe traces, métricas e logs das apps

2. Pré-requisitos

  • Docker + Docker Compose 2.x
  • ~4 GB RAM livres (8 GB mais confortável)
  • Portas: 3000, 9090, 3100, 4317/4318

3. Estrutura e docker-compose

observabilidade/
├── docker-compose.yml
├── prometheus/prometheus.yml
├── loki/loki-config.yml
├── otel/otel-collector-config.yml
└── grafana/provisioning/datasources/datasources.yml
$ cat docker-compose.yml
version: "3.8"

services:
  prometheus:
    image: prom/prometheus:v2.54.0
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--web.enable-lifecycle"
    ports:
      - "9090:9090"
    restart: unless-stopped

  loki:
    image: grafana/loki:3.0.0
    volumes:
      - ./loki/loki-config.yml:/etc/loki/local-config.yaml
      - loki_data:/loki
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    restart: unless-stopped

  grafana:
    image: grafana/grafana:11.1.0
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    ports:
      - "3000:3000"
    depends_on:
      - prometheus
      - loki
    restart: unless-stopped

  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.105.0
    volumes:
      - ./otel/otel-collector-config.yml:/etc/otelcol/config.yaml
    ports:
      - "4317:4317"
      - "4318:4318"
    depends_on:
      - prometheus
      - loki
    restart: unless-stopped

volumes:
  prometheus_data:
  loki_data:
  grafana_data:

4. Prometheus

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
  - job_name: "otel-collector"
    static_configs:
      - targets: ["otel-collector:8888"]

5. Loki

auth_enabled: false
server:
  http_listen_port: 3100
common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    instance_addr: 127.0.0.1
    kvstore:
      store: inmemory
schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

6. Grafana + datasources

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100
$ docker compose up -d

Grafana → http://localhost:3000 (admin / admin123)
Prometheus → http://localhost:9090

warn · Altere a senha do Grafana imediatamente em qualquer ambiente exposto.

7. OpenTelemetry Collector

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
processors:
  batch:
exporters:
  prometheus:
    endpoint: "0.0.0.0:8888"
  loki:
    endpoint: http://loki:3100/loki/api/v1/push
  logging:
    loglevel: info
service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheus, logging]
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [loki, logging]
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [logging]

8. Exporters

Adicione o node-exporter ao compose e o job correspondente no prometheus.yml para métricas de host. Instrumente apps com SDKs OTel apontando para localhost:4318 (HTTP) ou :4317 (gRPC).

9. Dashboards

  1. Grafana → Dashboards → Import
  2. Node Exporter oficial (ID 1860)
  3. Crie painéis LogQL no Loki para logs de containers
tip · Use labels consistentes (job, instance, service) para correlacionar métricas e logs.

10. Próximos passos

  • Adicionar Tempo/Jaeger para traces
  • Alertas no Grafana + Alertmanager
  • Instrumentar aplicações reais
  • Reverse proxy com TLS (Traefik/Nginx)
  • Versionar configs no Git

Stack leve o bastante para homelab e sólida para dev/staging. Em produção, refine retenção, HA e segurança.

11. Configurações explicadas

docker-compose.yml

TrechoO que faz
image: prom/prometheus:v2.54.0Imagem com a versão fixada, para o ambiente não mudar sozinho.
./prometheus/prometheus.yml:/etc/prometheus/prometheus.ymlMonta o arquivo de configuração do host dentro do container.
prometheus_data:/prometheusVolume nomeado: os dados sobrevivem à recriação do container.
--config.file e --storage.tsdb.pathIndicam o arquivo de configuração e a pasta do banco de séries temporais.
--web.enable-lifecyclePermite recarregar a configuração com uma chamada HTTP, sem reiniciar.
ports: "9090:9090"Formato porta-do-host:porta-do-container.
restart: unless-stoppedReinicia o container após falhas ou reinício do host, a menos que você o pare.
depends_onDefine a ordem de início. Ela não espera o serviço estar pronto.
GF_SECURITY_ADMIN_USER e GF_SECURITY_ADMIN_PASSWORDUsuário e senha iniciais do Grafana.
GF_USERS_ALLOW_SIGN_UP=falseImpede que qualquer pessoa crie uma conta.
ServiçoPortaPara que serve
Prometheus9090interface e API de métricas
Loki3100recebe e consulta logs
Grafana3000painéis e consultas
OTel Collector4317 e 4318recebe dados por OTLP (gRPC e HTTP)

prometheus.yml, Loki e Grafana

ConfiguraçãoO que faz
scrape_interval: 15sA cada 15 segundos o Prometheus coleta as métricas dos alvos.
evaluation_interval: 15sFrequência de avaliação das regras de alerta.
job_name e static_configs: targetsNome do grupo de coleta e a lista de endereços a consultar.
auth_enabled: false (Loki)Sem multi-tenant, adequado a um único ambiente.
replication_factor: 1 e store: inmemoryInstância única, sem cluster.
access: proxy (Grafana)O Grafana faz a consulta ao servidor, em vez do navegador.
url: http://prometheus:9090Usa o nome do serviço na rede do Compose.

OpenTelemetry Collector

BlocoO que faz
receivers: otlpRecebe dados no formato OTLP, por gRPC (4317) ou HTTP (4318).
processors: batchAgrupa os dados antes de enviar, o que reduz o número de requisições.
exportersDestinos: prometheus para métricas, loki para logs e logging para depurar na saída do container.
service: pipelinesLiga receptores, processadores e exportadores para cada tipo de sinal. Aqui os traces só vão para o logging, pois a stack não tem backend de traces.

12. Como conferir se subiu

docker compose up -d
docker compose ps
curl -s http://localhost:9090/-/ready
curl -s http://localhost:3100/ready
docker compose logs -f otel-collector
ComandoO que esperar
docker compose psos quatro serviços em running
curl .../9090/-/readya mensagem de que o Prometheus está pronto
curl .../3100/readyready. O Loki pode levar alguns segundos após subir
docker compose logs -f otel-collectorerros de configuração, se houver

13. Erros comuns e como resolver

SintomaCausa provávelSolução
O Collector falha com "address already in use" na porta 8888O exporter Prometheus usa a mesma porta das métricas internas do próprio Collector.Mude o exporter para 0.0.0.0:8889 (como no artigo de OpenTelemetry) e o alvo do prometheus.yml para otel-collector:8889.
Um alvo aparece como DOWN no PrometheusNome de serviço ou porta errados.Abra Status → Targets e confira o erro exibido.
Aviso "the attribute version is obsolete"O Compose atual ignora o campo version.Remova a linha version: "3.8". O restante continua igual.
O exportador logging não é reconhecidoVersões novas do Collector o substituíram pelo debug.Troque o nome do exportador ou mantenha a versão fixada da imagem.
Alguém acessa o Grafana com admin123A senha padrão do exemplo ficou em uso.Troque a senha e evite deixá-la no arquivo versionado.
$ next

Precisa de infraestrutura na prática?

falar com a IRN Devs → serviços

Quer aplicar isso ao seu contexto?

Se esse problema existe na sua operação, podemos analisar o cenário em um diagnóstico gratuito de 30 minutos.

solicitar diagnóstico gratuito →

Leia também