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
⚠ Raw values are visible on this screen only. Saved board data and every export stay redacted — exports never contain raw values.
Time range in file: —
This board was restored from this browser's storage — stored samples are the redacted copies by design. The raw-view toggle has no effect on restored boards.
| Severity | Problem (first sample line) | Count | First seen | Last seen |
|---|
No repeated problems — every entry in this file was seen exactly once. Check the singletons below.
Singletons — entries seen exactly once
Grouping is deterministic normalisation: timestamps, IDs, IPs and numbers are masked, then entries are matched on the masked message plus the top application frame. It groups — it does not diagnose. Check a group's samples before you act on it.
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
- Bound the window.
docker logs --since 30maround the incident. All-history exports mostly add noise and gigabytes. - 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. - 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.
- 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.