Monitorar containers Docker com Prometheus e Grafana via Docker Compose — guia prático
Por John Pires · 14 de março de 2026

Introducao ao problema
Executar containers Docker em desenvolvimento ou produção é rotina. Mas saber se seus containers estão saudáveis, quanto CPU e memória consomem, como latência e erros evoluem ao longo do tempo exige métricas e visualização. Sem isso você reage a incêndios em vez de prevenir. Prometheus e Grafana formam a dupla padrão em observability para métricas: Prometheus coleta e armazena séries temporais, Grafana exibe painéis com métricas e alertas.
Este artigo mostra, passo a passo, como montar um ambiente local com Docker Compose que reúne: sua aplicação instrumentada, Prometheus, Grafana e cAdvisor para métricas de container. O objetivo é prático: ter um stack inicial, entendível, que você pode reproduzir em qualquer máquina com Docker.
Vou explicar conceitos mínimos, configurações que realmente funcionam e erros comuns que aparecem para quem está começando. Nada de floreios: arquivos reais, comandos e verificação final do resultado.
Pre-requisitos e setup
Antes de começar, verifique que você tem as ferramentas básicas instaladas. Estas são obrigatórias para seguir os passos sem improviso:
- Docker Engine (versão moderna compatível com Compose V2).
- Docker Compose (v2 integrado ao Docker CLI ou standalone).
- Terminal com acesso sudo se necessário.
- Editor de texto para criar arquivos docker-compose.yml, prometheus.yml e arquivos da aplicação.
Se estiver em Windows ou Mac, use Docker Desktop. Em Linux, instale Docker e, se necessário, adicione seu usuário ao grupo docker para evitar sudo. Teste com docker version e docker compose version.
Cheque rápido de ambiente
Rode os comandos abaixo e confirme que não há erros. Eles salvam tempo em debugging.
docker --version
docker compose version
Se ambos retornarem versões, siga. Se o compose não for reconhecido, instale-o ou use docker-compose (legacy) ajustando os comandos.
O que vamos criar
Nosso stack será composto por estes serviços declarados no docker-compose.yml:
- prometheus: coleta métricas via scrape dos endpoints expostos.
- grafana: painel para visualizar métricas e importar dashboards prontos.
- cadvisor: expõe métricas detalhadas dos containers Docker (CPU, memória, I/O).
- app: uma aplicação Node.js instrumentada com prom-client que expõe /metrics.
Essa composição é suficiente para um ambiente de aprendizado que replica conceitos usados em produção.
Tutorial guiado passo a passo
Abaixo estão os arquivos mínimos. Cada bloco tem contexto, o que faz e o que acontecerá ao executá-lo.
1) Arquivo docker-compose.yml
O arquivo central orquestra containers. Ele cria uma rede, monta volumes para persistência de Prometheus e Grafana e liga os serviços. Salve como docker-compose.yml na raiz do projeto.
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'
networks:
- monitoring
grafana:
image: grafana/grafana:8.5.0
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
ports:
- '3000:3000'
networks:
- monitoring
cadvisor:
image: gcr.io/google-containers/cadvisor:latest
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- '8080:8080'
networks:
- monitoring
app:
build: ./app
ports:
- '8081:8080'
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge
O que acontece: ao rodar docker compose up -d, você terá Prometheus em 9090, Grafana em 3000, cAdvisor em 8080 e sua app em 8081. Prometheus usará o arquivo de configuração que vamos criar a seguir.
2) Arquivo prometheus.yml
Prometheus precisa saber onde puxar métricas. Esse arquivo define jobs de scrape para o app e para cAdvisor. Salve como prometheus.yml na raiz do projeto.
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'app'
static_configs:
- targets: ['app:8080']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
O que acontece: Prometheus vai tentar acessar os endpoints app:8080/metrics e cadvisor:8080/metrics usando a rede do compose. Se tudo estiver no mesmo compose e na mesma rede, os nomes de serviço resolvem automaticamente.
3) Aplicacao Node.js instrumentada (app)
Criamos uma aplicação minimalista que simula trabalho e expõe métricas via prom-client. Estrutura: pasta app com Dockerfile e app.js. Essa app demonstra métricas de latência e contagem de requisições reais, não um simples hello world.
// arquivo: app/app.js
const express = require('express')
const client = require('prom-client')
const register = client.register
const httpRequestDurationMicroseconds = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duracao das requisicoes HTTP em segundos',
labelNames: ['method', 'route', 'code']
})
const counter = new client.Counter({
name: 'http_requests_total',
help: 'Contador de requiscos HTTP',
labelNames: ['method', 'route', 'code']
})
const app = express()
app.get('/work', async (req, res) => {
const end = httpRequestDurationMicroseconds.startTimer()
// simula variacao de carga
const ms = Math.random() * 500
await new Promise(r => setTimeout(r, ms))
counter.inc({ method: 'GET', route: '/work', code: 200 })
end({ method: 'GET', route: '/work', code: 200 })
res.status(200).send('ok')
})
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType)
res.end(await register.metrics())
})
app.listen(8080, () => console.log('app listening on 8080'))
O que acontece: a rota /work gera latência variável e incrementa métricas. /metrics expõe tudo que Prometheus irá raspar. Esse é um padrão real em microservices instrumentados com prom-client ou bibliotecas similares.
# arquivo: app/Dockerfile
FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 8080
CMD ["node", "app.js"]
O que acontece: a imagem resultante inicia a aplicação que expõe /metrics. Build é feito automaticamente pelo docker compose se você usar build: ./app.
4) Provisionamento básico do Grafana
Você pode configurar Grafana manualmente no browser, mas é mais interessante automatizar a datasource via provisioning. Crie o arquivo provisioning/datasources/prometheus.yml e monte no container se desejar automação. Exemplo mínimo abaixo.
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
O que acontece: ao subir o Grafana com esse arquivo montado em /etc/grafana/provisioning/datasources, ele terá a fonte Prometheus pronta, evitando configuração manual.
Erros comuns e armadilhas
Mesmo em ambiente local você vai trombar com problemas repetidos. Abaixo, as falhas mais comuns e como resolver rapidamente.
Erro 1: Prometheus não encontra serviço - geralmente causado por target errado ou serviço fora da mesma rede. Confirme que no compose os serviços estão no mesmo network e use docker compose ps para ver nomes e portas.
Erro 2: /metrics com HTML ou erro 500 - verifique a implementação do endpoint; prom-client e bibliotecas similares retornam texto plano com content-type text/plain; problemas na rota fazem Prometheus marcar como bad status.
Erro 3: Grafana sem datasource - verifique logs do container Grafana e a montagem dos arquivos de provisioning. Muitas vezes o arquivo está no diretório errado ou com permissões incorretas.
Dica: utilize docker compose logs -f para inspecionar rapidamente por que um serviço falhou.
Resultado final funcionando
Com os arquivos no lugar execute:
docker compose up -d --build
O comando constroi a imagem da app e sobe todo o ambiente. Cheque status com docker compose ps. Acesse os serviços:
- Grafana: http://localhost:3000 (user: admin, senha: admin ou o que definiu)
- Prometheus: http://localhost:9090 (query e targets em Status)
- cAdvisor: http://localhost:8080
- App: http://localhost:8081/work e /metrics
No Prometheus, abra Status > Targets e confirme app:8080 e cadvisor:8080 como UP. Se estiverem, os dados estão sendo coletados. Teste uma query simples em Prometheus:
http_requests_total
Em Grafana, crie um dashboard novo e adicione um painel com a query http_requests_total para ver contagem de requisições. Ou importe dashboards prontos para cAdvisor ou Docker engine, economizando tempo.
Se quiser automatizar dashboards, use a API do Grafana ou provisioning de dashboards via JSON. Para começar, a criação manual via UI é suficiente e mais didática.
Desafio para o leitor praticar
Prática é essencial. Faça o desafio abaixo para consolidar o que aprendeu.
- Adicione um job de scrape que colete métricas de um segundo serviço que você constrói: uma API que registra erros e tempo médio de resposta por rota.
- Crie regras de gravação (recording rules) no Prometheus para processar o 95º percentil da latência e reduzir custo de queries no Grafana.
- Configure um alerta simples no Prometheus Alertmanager (adicione-o ao docker-compose) que envie uma notificação quando a CPU do container ultrapassar 80% por mais de 2 minutos.
Esses passos forçam você a alterar prometheus.yml, adicionar regras e integrar o Alertmanager, práticas reais em ambientes de produção.
Conclusao
Montar um stack Prometheus + Grafana via Docker Compose é uma forma rápida de introduzir monitoramento em projetos. A combinação de uma app instrumentada, cAdvisor e Prometheus cobre métricas essenciais de aplicação e de container.
O fluxo prático: instrumente a aplicação, exponha /metrics, configure Prometheus para scrapes e use Grafana para painéis e alertas. Esse fluxo é o mesmo em produção, apenas adaptado para Kubernetes ou infra gerenciada.
Erros comuns são previsíveis: problemas de rede do compose, endpoints /metrics mal implementados e arquivos de provisioning mal montados. Com os comandos e arquivos mostrados você tem um ambiente funcional para aprender e escalar.
Agora execute o compose, verifique targets no Prometheus, crie um painel no Grafana e implemente o desafio. Monitoramento é iterativo: comece com o essencial e adicione alertas e regras conforme for entendendo o comportamento do seu sistema.
Se precisar, copie os arquivos do tutorial, ajuste caminhos e rode os containers em uma VM ou máquina local. Esse é o primeiro passo prático rumo a uma observability madura.
Assuntos: DevOps, Docker, prometheus, grafana, docker-compose, observability, cadvisor
Leia também
Portfólio técnico: montar um case deployável em 1 hora com GitHub Actions e Terraform
Guia prático para criar um portfólio técnico deployável em 1 hora usando GitHub Actions e Terraform: estrutura de repositório, Terraform para S3+CloudFront…
Testcontainers e GitHub Actions: testar imagens Docker na CI corretamente
Guia prático de como rodar testes de integração com imagens Docker usando Testcontainers no GitHub Actions: padrões certos e anti-patterns, workflows…
Testes em CI com GitHub Actions e Docker Compose para Postgres e Redis
Aprenda a rodar testes de integração no CI usando GitHub Actions e Docker Compose com Postgres e Redis. Guia passo a passo para iniciantes: arquivos…
Escanear imagens Docker no CI com Trivy e GitHub Actions — falhe por CVSS
Aprenda a escanear imagens Docker no CI com Trivy e GitHub Actions e a fazer o pipeline falhar quando uma vulnerabilidade atingir um limiar CVSS. Passo a…
GitHub Actions: build, testar em container e publicar imagem no GHCR
Pipeline prática: build de imagem Docker, executar testes no container carregado e publicar no GHCR usando GitHub Actions. Código e workflow para iniciar e…
Ambientes de preview em PRs com GitHub Actions e Docker Compose — passo a passo
Aprenda a criar ambientes de preview para PRs usando GitHub Actions e Docker Compose. Mostro o jeito errado e o certo, com exemplos reais, scripts de saúde e…