Logs em containers Docker

1. Fundamentos de Logs no Docker

O Docker coleta automaticamente tudo que um container envia para stdout (saída padrão) e stderr (saída de erro padrão). O comando principal para acessar esses logs é docker logs.

# Visualizar logs do container
docker logs meu-container

# Seguir logs em tempo real (como tail -f)
docker logs --follow meu-container

# Exibir apenas as últimas 50 linhas
docker logs --tail 50 meu-container

# Adicionar timestamps a cada linha
docker logs --timestamps meu-container

# Combinar opções: últimos 100 logs com timestamps
docker logs --tail 100 --timestamps meu-container

É crucial entender que logs escritos em arquivos dentro do container (ex: /var/log/app.log) não são capturados pelo docker logs. O Docker gerencia apenas o que chega via stdout/stderr. O armazenamento local dos logs fica em /var/lib/docker/containers/[ID]/[ID]-json.log quando usando o driver padrão json-file.

2. Drivers de Log do Docker

O Docker oferece diversos drivers de log para rotear os logs dos containers. A configuração global é feita no arquivo /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Principais drivers e seus usos:

Driver Descrição Ideal para
json-file Padrão, logs em arquivos JSON locais Desenvolvimento, testes
journald Envia logs para systemd-journald Ambientes Linux com systemd
syslog Envia para syslog local ou remoto Infraestrutura legada
awslogs Envia para Amazon CloudWatch Ambientes AWS
gelf Formato Graylog Extended Log Graylog, Elasticsearch
fluentd Envia para Fluentd Pipelines de logging centralizado

Para configurar por container:

docker run --log-driver syslog --log-opt syslog-address=udp://192.168.1.100:514 nginx

Prós e contras em produção: json-file é simples mas não escala; fluentd e awslogs oferecem melhor centralização; journald integra bem com ferramentas Linux nativas.

3. Boas Práticas de Logging em Containers

Aplicações em containers devem seguir o princípio 12-factor: logs como fluxo de eventos, sempre para stdout/stderr.

# Ruim: escrever em arquivo interno
python app.py >> /var/log/app.log 2>&1

# Bom: escrever direto no stdout
python app.py

Estruturação de logs em JSON facilita análise posterior:

# Logs não estruturados (difícil de parsear)
2024-01-15 10:30:45 ERRO conexão falhou com banco

# Logs em JSON (fácil de filtrar com jq)
{"timestamp":"2024-01-15T10:30:45Z","level":"ERROR","service":"api","message":"conexão falhou com banco","db_host":"db-prod-01"}

Controle de verbosidade: evite logs de debug em produção. Configure níveis via variáveis de ambiente:

docker run -e LOG_LEVEL=warn minha-app

4. Gerenciamento de Tamanho e Rotação de Logs

Sem rotação, logs podem consumir todo o disco. Configure limites no driver json-file:

# Configuração no daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "5"
  }
}

Para containers já rodando, faça limpeza manual:

# Verificar tamanho dos logs
du -sh /var/lib/docker/containers/*/*-json.log

# Truncar logs de um container específico
truncate -s 0 /var/lib/docker/containers/[ID]/[ID]-json.log

# Usar docker logs com tail para arquivos corrompidos
docker logs --tail 100 container-problema > logs_recentes.txt

Riscos de disco cheio: Um container com loop infinito de logs pode travar o host. Estratégias de mitigação:
- Monitorar uso de disco via Prometheus/node_exporter
- Configurar rotação automática com logrotate para o diretório do Docker
- Usar drivers remotos que não acumulam logs localmente

5. Coleta Centralizada de Logs com Docker

Para ambientes com múltiplos hosts, a coleta centralizada é essencial. Exemplo com Fluentd:

# Executar container com driver fluentd
docker run --log-driver fluentd --log-opt fluentd-address=localhost:24224 nginx

# Configuração do Fluentd (fluent.conf)
<source>
  @type forward
  port 24224
</source>

<match docker.**>
  @type elasticsearch
  host elasticsearch-prod
  port 9200
  logstash_format true
</match>

Para aplicações legadas que escrevem em arquivos, use sidecar containers:

# docker-compose.yml
services:
  app-legada:
    image: minha-app-antiga
    volumes:
      - logs-volume:/var/log/app

  log-collector:
    image: fluent/fluentd
    volumes:
      - logs-volume:/logs
    command: fluentd -c /fluentd/etc/fluent.conf

6. Logs em Ambientes Kubernetes

No Kubernetes, kubectl logs substitui docker logs. Diferenças fundamentais:

# Docker
docker logs container-id

# Kubernetes - logs de um pod
kubectl logs pod-name

# Kubernetes - logs de container específico em pod multi-container
kubectl logs pod-name -c container-name

# Seguir logs em tempo real
kubectl logs -f pod-name

# Últimas N linhas
kubectl logs --tail=100 pod-name

Para logs de pods com múltiplos containers, o K8s suporta --all-containers=true (v1.14+):

kubectl logs --all-containers=true deployment/api

Ferramentas de logging no ecossistema K8s:
- Fluentd + Elasticsearch + Kibana (EFK): Stack clássica
- Loki + Promtail + Grafana: Leve, sem indexação pesada
- Datadog, New Relic: SaaS com agentes DaemonSet

7. Segurança e Auditoria de Logs

Logs podem conter dados sensíveis. Nunca logue senhas, tokens ou dados pessoais:

# RUIM - token exposto no log
{"user":"admin","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}

# BOM - token mascarado
{"user":"admin","token":"***MASCARADO***"}

Para auditoria do Docker daemon, habilite logs do dockerd:

# Iniciar dockerd com debug e logs detalhados
dockerd --log-level debug --log-opt max-size=50m

# Visualizar logs do daemon
journalctl -u docker.service --since "1 hour ago"

Controle de acesso: apenas usuários no grupo docker podem executar docker logs. Para logs de volumes compartilhados, use permissões Unix:

# Volume com permissões restritas
docker run -v /host/logs:/app/logs:ro minha-app

8. Monitoramento e Troubleshooting com Logs

Correlacione logs com métricas para troubleshooting eficiente:

# Identificar OOM killer
docker logs container-oom | grep -i "killed"

# Verificar logs de healthcheck com timestamps
docker logs --since 5m healthcheck-container

# Combinar docker stats com logs
docker stats container-problema --no-stream &
docker logs --follow container-problema

Comandos úteis para análise:

# Filtrar erros das últimas 2 horas
docker logs --since 2h app-production | grep -i error

# Analisar logs JSON com jq
docker logs api-container | jq 'select(.level=="ERROR") | {message, timestamp}'

# Contar ocorrências de erro por minuto
docker logs app --since 1h | grep "ERROR" | cut -c1-16 | sort | uniq -c

Erros comuns em containers:
- OOM: Container morto pelo kernel. Verifique docker inspect e logs do host
- Healthcheck falhando: Logs mostram timeout ou resposta inesperada
- Crashes recorrentes: Use docker logs --tail 20 --timestamps para ver o último erro antes do crash

Referências