cAdvisor: métricas de containers Docker

cAdvisor (Container Advisor) do Google coleta métricas em tempo real de cada container Docker, uso de CPU, memória, rede e I/O de disco. Integrado ao Prometheus, você monitora cada microserviço individualmente: quem está consumindo mais memória? qual container tem CPU throttling?

Instalar cAdvisor com Docker Compose

Adicionar cAdvisor ao stack de monitoramento:

yaml
# docker-compose.yml:
services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    privileged: true           # necessário para acessar cgroups do host
    devices:
      - /dev/kmsg:/dev/kmsg
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
      - /cgroup:/cgroup:ro
    ports:
      - "127.0.0.1:8080:8080"
    restart: unless-stopped
    command:
      - '--housekeeping_interval=10s'   # intervalo de coleta (padrão: 1s — alto!)
      - '--docker_only=true'            # apenas containers Docker (pular VM/bare-metal)
      - '--store_container_labels=false'  # reduzir cardinalidade de labels

# prometheus.yml — adicionar job cAdvisor:
scrape_configs:
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']
    metric_relabel_configs:
      # Remover métricas de baixo valor para reduzir volume:
      - source_labels: [__name__]
        regex: 'container_(network_tcp_usage_total|tasks_state|cpu_load_average_10s)'
        action: drop

Métricas do cAdvisor e queries PromQL

As principais métricas e como consultá-las:

bash
# Métricas principais do cAdvisor:
# container_cpu_usage_seconds_total  → CPU total usada pelo container
# container_memory_usage_bytes       → Memória RSS do container
# container_memory_limit_bytes       → Limite de memória configurado
# container_network_receive_bytes_total  → Bytes recebidos na rede
# container_network_transmit_bytes_total → Bytes enviados na rede
# container_fs_reads_bytes_total     → I/O de leitura
# container_fs_writes_bytes_total    → I/O de escrita

# CPU usage % por container:
sum by (name) (
  rate(container_cpu_usage_seconds_total{
    image!="",
    name!=""
  }[5m])
) * 100

# Memória por container:
container_memory_usage_bytes{image!="", name!=""}
/ 1024 / 1024  # converter para MB

# % de memória usada em relação ao limite:
container_memory_usage_bytes{image!="", name!=""}
/
container_memory_limit_bytes{image!="", name!=""} * 100

# Network I/O por container (bytes/s):
rate(container_network_receive_bytes_total{name!=""}[5m])

# CPU throttling % (container limitado por CPU limit):
rate(container_cpu_throttled_seconds_total{name!=""}[5m])
/ rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100

Alertas para containers

Regras de alerta para containers com alto consumo ou fora do ar:

yaml
# alerts/containers.yml:
groups:
  - name: containers
    rules:

      # Container consumindo mais de 90% do limite de memória:
      - alert: ContainerMemoriaAlta
        expr: |
          container_memory_usage_bytes{name!=""}
          / container_memory_limit_bytes{name!=""} * 100 > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Container {{ $labels.name }} com memória acima de 90%"
          description: "Uso: {{ $value | printf "%.1f" }}% do limite"

      # Container reiniciando com frequência (possível crash loop):
      - alert: ContainerReiniciandoMuito
        expr: |
          increase(container_last_seen{name!=""}[1h]) < -2
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Container {{ $labels.name }} reiniciou mais de 2x na última hora"

      # Container com CPU throttling alto:
      - alert: ContainerCpuThrottling
        expr: |
          rate(container_cpu_throttled_seconds_total{name!=""}[5m])
          / rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 > 50
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Container {{ $labels.name }} com CPU throttling acima de 50%"
          description: "Considere aumentar o cpu limit. Throttling atual: {{ $value | printf "%.1f" }}%"

Dashboard Grafana para containers

Importar dashboard pronto e criar painéis customizados:

bash
# Dashboard da comunidade Grafana para cAdvisor:
# ID 14282 — Cadvisor exporter (bem detalhado)
# ID 193   — Docker and system monitoring
# Importar: Grafana → + → Import → inserir ID

# Painel customizado: Top 5 containers por CPU:
topk(5,
  sum by (name) (
    rate(container_cpu_usage_seconds_total{
      image!="",
      name!="",
      name!~"cadvisor|prometheus|grafana"
    }[5m])
  ) * 100
)

# Painel: Total de memória por stack (agrupando por compose project):
sum by (container_label_com_docker_compose_project) (
  container_memory_usage_bytes{
    container_label_com_docker_compose_project!=""
  }
) / 1024 / 1024

# Painel: Containers rodando vs parados:
count by (name) (container_last_seen{name!=""} > time() - 30)

# Variável de template no Grafana para selecionar container:
# Label values query: label_values(container_cpu_usage_seconds_total{image!=""}, name)

Reduzir cardinalidade do cAdvisor

Controlar volume de métricas para não sobrecarregar o Prometheus:

yaml
# cAdvisor gera muitas métricas por padrão — ajustar para reduzir volume:

# docker-compose.yml — flags de otimização:
command:
  - '--housekeeping_interval=15s'         # coleta a cada 15s (não 1s)
  - '--docker_only=true'                  # apenas Docker (ignorar outros runtimes)
  - '--disable_metrics=accelerator,cpu_topology,disk,memory_numa,tcp,udp,percpu,sched,process,hugetlb,referenced_memory,resctrl,cpuset'

# Manter apenas: cpu, memory, network, diskIO
# --disable_metrics lista o que desabilitar:
# accelerator, advtcp, cpu_topology, cpuset, disk, hugetlb
# memory_numa, process, referenced_memory, resctrl, sched, tcp, udp

# relabel no Prometheus para descartar séries desnecessárias:
# prometheus.yml:
metric_relabel_configs:
  # Manter apenas containers reais (não infra do Docker):
  - source_labels: [container_label_com_docker_swarm_service_name]
    regex: '.+'
    action: keep
  # Ou filtrar por nome:
  - source_labels: [name]
    regex: 'minha-api|postgres|redis|nginx'
    action: keep

# Verificar número de séries ativas:
curl -s 'http://localhost:9090/api/v1/query?query=count({job="cadvisor"})' | jq .

Não quer configurar manualmente?

Implante o VPS para Docker em menos de 5 minutos com a Runstack. Infraestrutura da OPEN Datacenter, com servidores em São Paulo.

Perguntas frequentes

Sim, cAdvisor precisa de privileged: true para acessar os cgroups do host e coletar métricas de todos os containers. Em produção isso é um risco de segurança (container privilegiado pode escapar para o host). Mitigação: mantenha cAdvisor em rede interna (porta apenas em 127.0.0.1), atualize regularmente a imagem, use a imagem oficial do Google Container Registry. Alternativas sem privileged: Prometheus Docker SD com métricas mais limitadas, ou Datadog Agent com capabilities específicas em vez de privileged.

O padrão de 1 segundo é excessivo para maioria dos casos, gera carga desnecessária de CPU e volume de dados no Prometheus. Recomendado: 10-15 segundos para produção. Valores menores que 5s só fazem sentido para detectar spikes de CPU em tempo real (ex: debug de latência). O scrape interval do Prometheus (padrão: 15s) define a frequência de coleta, configurar housekeeping < scrape interval não traz benefício.

docker stats: ferramenta interativa para inspeção manual rápida, sem persistência, sem alertas, sem histórico. cAdvisor: coleta contínua, integra com Prometheus/Grafana, histórico configurável, alertas automáticos. Para debug rápido: docker stats container_name. Para monitoramento de produção: cAdvisor + Prometheus. cAdvisor também tem UI web própria em :8080 para visualização imediata sem Grafana.

Configure limits no docker-compose.yml (deploy.resources.limits), o cAdvisor expõe container_memory_limit_bytes e você pode calcular o percentual de uso. Sem limites configurados: container_memory_limit_bytes retorna um valor enorme (memória total do host) e o percentual não faz sentido. Boa prática: sempre configure memory limit nos services de produção, evita que um container com memory leak consuma toda a RAM do servidor.

cAdvisor é integrado ao kubelet no Kubernetes, você não precisa instalar separadamente em clusters K8s. O Prometheus Operator e kube-state-metrics cobrem o monitoramento de containers e recursos de cluster. Para K8s: use kube-prometheus-stack (Helm chart) que inclui Prometheus, Grafana, Alertmanager e todas as regras de alerta necessárias. cAdvisor standalone é mais relevante para Docker Compose em VPS.