iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Logging

Docker logging: stdout / stderr capture, log drivers, rotation, and the patterns for aggregating + searching container logs.

Docker — logging

EXAMPLE
# ===== The model =====
# Containers write to stdout / stderr.
# Docker captures via a LOG DRIVER and forwards or stores.

# ===== Default driver: json-file =====
# Logs stored in /var/lib/docker/containers/<id>/<id>-json.log
# Unbounded by default — configure rotation!

docker run -d --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  --name api myapp

# Or set defaults in /etc/docker/daemon.json:
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

# ===== View =====
docker logs <container>
docker logs -f <container>           # follow
docker logs --tail 100 <container>
docker logs --since 30m <container>
docker logs --timestamps <container>

# Multi-container (compose):
docker compose logs -f
docker compose logs -f api db

# stern for fancier multi-container tail (works for docker too via plugins; Kubernetes-native).

# ===== Other drivers =====
# - none           drop logs (last resort)
# - syslog         send to local syslog daemon
# - journald       send to systemd journal
# - fluentd        ship to Fluentd / Fluent Bit
# - awslogs        CloudWatch Logs
# - gcplogs        Google Cloud Logging
# - splunk         Splunk
# - gelf           Graylog Extended Log Format
# - local          binary, compressed JSON (smaller than json-file)

# Pick driver via --log-driver or daemon.json.

# ===== Structured JSON logs =====
# Inside containers, log structured JSON:
{
  "ts": "2024-04-10T03:14:00Z",
  "level": "info",
  "msg": "request handled",
  "user_id": "u-1",
  "route": "/api/users"
}

# Shippers parse and index by field; humans grep less.

# ===== Fluent Bit example =====
# Ship docker container logs to Loki:
docker run -d --log-driver fluentd \
  --log-opt fluentd-address=fluentbit:24224 \
  myapp

# fluentbit.conf:
[INPUT]
  Name        forward
  Listen      0.0.0.0
  Port        24224
[OUTPUT]
  Name        loki
  Host        loki
  Match       *
  Labels      job=docker

# ===== Logs on Kubernetes =====
# Don't configure log drivers in Kubernetes; let kubelet capture stdout/stderr,
# then run Fluent Bit / Vector as a DaemonSet.

# ===== Best practices in app code =====
# - Write to stdout / stderr; not to files inside the container (lost on restart)
# - Structured JSON; one record per line
# - Include trace / request id
# - Log level filter at the source

# ===== Sensitive data =====
# - Never log secrets, tokens, passwords, full request bodies
# - Mask PII at the producer
# - Shorten retention for high-volume logs

# ===== Patterns =====
# - log-opt max-size + max-file (avoid filling disk)
# - JSON logs from every app
# - Ship to a central store (Loki / Elastic / CloudWatch)
# - Distinct logs for ERROR vs INFO; alert on ERROR rate

# ===== Pitfalls =====
# - Unbounded json-file driver -> disk full -> docker down
# - Logging to files inside the container (data loss + no rotation)
# - Plain-text logs that need regex parsing
# - Same log shipper config across vastly different services -> noisy

Why it matters

Docker logging: stdout/stderr -> log driver -> store. Always rotate (max-size + max-file), prefer JSON output, ship to a central store (Loki/Elastic/CloudWatch). On Kubernetes let kubelet capture and Fluent Bit ship. Mask PII at the producer; do not let logs become your secret leak path.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Default JSON-file driver; switch to syslog / fluentd / awslogs in prod.
docker run --log-driver json-file --log-opt max-size=10m my-api
Try it Yourself »

Discussion

Loading…