Home › Guides › Docker logs triage

Docker logs triage

Direct answer: export the incident window (docker logs --since, or docker compose logs for one service), then group the file: container output is interleaved and repetitive by design, so distinct-problem grouping is what turns it into answers. The grouper below reads Docker json-file records and Compose-prefixed output natively — drop the exported file in.

Group this Docker log

Drop a log file here — or click to choose one. Files are read in slices on this device (designed for logs up to ~500 MB); nothing is uploaded.

Why container logs need grouping more than most

A container that crash-loops writes the same stack trace hundreds of times, interleaved with every other service's noise. Reading docker logs output top-to-bottom, you can't tell a crash-loop (one problem, 400 occurrences) from broad breakage (400 problems, one occurrence each) — and the response is completely different. Grouping separates those two shapes at a glance: check the board's distinct-problem count against its entry count.

The triage order for containers

  1. Bound the window. docker logs --since 30m around the incident. All-history exports mostly add noise and gigabytes.
  2. Separate services if you can. One service per export (docker compose logs api) triages cleaner than the whole stack; the channel/prefix still groups correctly in a combined file, but single-service boards read faster.
  3. Group, then look at the top FATAL/ERROR group. In a crash-loop it will be one group with a huge count and a first-seen that matches the deploy or the config change.
  4. Check singletons. The one-off line right before the loop starts ("config file not found", "permission denied on /data") is frequently the actual cause; the loop is just the symptom.

Reading the two Docker shapes

With the default json-file driver, each line is a JSON record — the grouper unwraps it and treats the inner text as the log line, using the record's timestamp. With Compose, lines arrive prefixed (api_1  | …); the prefix is stripped during parsing and the service's own logger name becomes the channel. Either way the same grouping applies — see the grouping method for what happens next, and Kubernetes logs triage when the containers graduate to pods.

Frequently asked questions

My container log is a wall of JSON. Can it still be grouped?

Yes. Docker’s json-file driver wraps every line in a record with log, stream and time fields. The grouper unwraps those records and feeds the inner lines through the same assembly as plain text, so a Java or Python trace printed inside a container assembles and groups exactly as it would on a host.

How do I get the log out of Docker in the first place?

docker logs <container> > app.log captures stdout/stderr; add --since to bound it (docker logs --since 2h) — triage rarely needs more than the incident window. For Compose, docker compose logs <service> gives you the service-prefixed format, which the grouper also reads. Export to a file rather than piping through a terminal, so nothing is truncated or coloured.

The log has ANSI colour codes in it. Problem?

Colour codes come from a TTY being attached; captured files (docker logs > file) normally don’t have them. If yours do, strip them before triage (sed with the escape-sequence pattern) — they sit inside message text and would split groups. Prevention: don’t allocate a TTY for services whose logs you keep.