DevOps Peach

Docker & Kubernetes · Docker in Real Projects – Operations and Docker Compose · Lesson 2 of 4

Runtime metrics and logging

docker stats reads metrics from cgroups; docker logs reads stdout/stderr through a logging driver, so turn on log rotation.

Practice interactively →

Metrics

docker stats shows CPU, memory usage/limit, network I/O, block I/O and PID count per container in real time. The numbers come from Linux cgroups (control groups), the kernel mechanism that limits and measures resources for groups of processes.

docker stats                 # streams continuously, Ctrl+C to quit
docker stats --no-stream     # one snapshot then exit (good for scripts)

Logging

docker logs shows what the main process writes to stdout/stderr. If the app writes to a file inside the container, docker logs does not see it; official images usually link log files to /dev/stdout.

flowchart LR
  APP["Main process<br/>stdout / stderr"] --> DRV["Logging driver"]
  DRV --> J["json-file (default)"]
  DRV --> L["local"]
  DRV --> F["fluentd / syslog / ..."]

The default driver is json-file, with no size limit: logs can fill the disk. Set rotation in /etc/docker/daemon.json:

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

daemon.json settings only apply to newly created containers; existing ones must be recreated. Change the driver for one container with --log-driver and --log-opt. With --log-driver none, docker logs has nothing to read.

Command Meaning
docker stats --no-stream One snapshot of metrics for all running containers
docker logs -f --tail 50 web Last 50 lines, then keep following
docker inspect -f '{{.HostConfig.LogConfig.Type}}' web The container's logging driver

Beyond docker stats

docker stats is live only; nothing is stored. For history and alerts, a common open-source stack is:

Component Role
cAdvisor Exposes per-container CPU, memory, network, and disk metrics
node-exporter Exposes host metrics
Prometheus Scrapes and stores metrics, evaluates alert rules
Grafana Dashboards on top of Prometheus

The Docker daemon can also expose its own metrics in Prometheus format with "metrics-addr": "127.0.0.1:9323" in daemon.json.

Limits make metrics meaningful

A container without limits can use the whole host. Set them with --memory and --cpus, or in Compose:

services:
  api:
    deploy:
      resources:
        limits: { cpus: "1.0", memory: 512M }

docker stats then shows memory against the limit, and a container that exceeds its memory limit is killed with exit code 137.

Choosing a logging driver

Driver Where logs go docker logs works?
json-file, local Files on the host Yes
journald systemd journal (journalctl CONTAINER_NAME=web) Yes
syslog, fluentd, gelf Central log servers Through dual logging cache
awslogs, gcplogs Cloud logging services Through dual logging cache

Recent Docker versions keep a local cache (dual logging) so docker logs still works with remote drivers.

Making logs useful

Write structured logs, for example one JSON object per line with level, timestamp, and request ID, so central tools such as the ELK stack, Grafana Loki, or a cloud service can filter them. docker logs --since 10m --timestamps web narrows the window while debugging.

Events

docker events streams what the daemon does: containers starting, dying, being killed for memory, health status changes. Filtering with --filter event=die is a quick way to spot crash loops.

Practice interactively →