Watch Docker Events Without Losing the Useful Detail
docker system events gives you a live stream for an incident, a bounded query for recent activity, and filters for one container or event type. Examples use Docker CLI 29.8.1 from docker-ce-cli package 5:29.8.1-1~ubuntu.24.04~noble.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need the Docker CLI and access to a Docker daemon, and your account must be allowed to contact it. Apart from a deliberately optional test-container step, this guide only reads the event stream: it does not remove containers, images, volumes or networks.
1. Check the installed command
Start by checking the command and its options:
$ docker --version
Docker version 29.8.1, build 4a63305
$ docker system events --help
Usage: docker system events [OPTIONS]
Get real time events from the server
docker system events and docker events are aliases; use the longer form in scripts when clarity matters. The command needs a reachable daemon even just to read events. If it reports a socket or permission error, check docker context show and your Docker access before adding sudo: running the CLI as root can select a different configuration and context entirely.
Checkpoint
Confirm the version is the one you intend to document and that the help lists --filter, --format, --since and --until.
2. Watch new events as they happen
Run the command without a start time:
$ docker system events
2026-09-23T10:14:02.123456789+01:00 container start 0123456789ab (image=example:1, name=example)
Without --since, the command waits for new and live events; it does not open with an unlimited history dump. Each line identifies a time, object type, action and object ID, followed by whatever attributes are available. The exact timestamp, ID and attributes depend on the event.
Leave this running in one shell while you investigate in another. Press Ctrl+C to stop the watcher; stopping it does not stop or change any Docker object.
To generate a known, temporary event sequence for practice, use a test image and an explicitly named container, only if pulling and running that image is acceptable in your environment:
$ docker create --name events-test alpine:latest true
$ docker start events-test
$ docker stop events-test
$ docker rm events-test
These commands do change Docker state, and the last one removes the test container. Skip them on a production daemon or anywhere image pulls are not approved. If you stop partway through, after create or start, recover with docker rm -f events-test once you are certain that name belongs to this test.
3. Replay a recent, bounded window
Use --since with a Go duration to inspect recent history. This asks for the last three minutes:
$ docker system events --since 3m --until 0s
2026-09-23T10:12:41.500000000+01:00 container die 0123456789ab (image=example:1, name=example)
2026-09-23T10:12:41.600000000+01:00 container stop 0123456789ab (image=example:1, name=example)
- Accepted formats.
--sinceand--untiltake Unix timestamps, supported date formats such as2026-09-23, RFC3339 timestamps, or durations such as10mand1h30m. - Durations are relative to your client clock, not the daemon's, and a date with no timezone offset uses your local timezone: use an explicit offset when a query must be unambiguous.
- Use --until as a guard rail against leaving a command attached to a terminal indefinitely.
For a fixed absolute interval, use timestamps with an offset:
$ docker system events \
--since '2026-09-23T09:00:00+01:00' \
--until '2026-09-23T09:05:00+01:00'
If a bounded query prints nothing, that can simply mean no matching events survived in the interval; it is not proof the daemon was idle outside it.
4. Narrow the stream with filters
Filters use key=value. This shows only container stop events:
$ docker system events \
--since 30m \
--filter 'type=container' \
--filter 'event=stop'
2026-09-23T10:13:02.000000000+01:00 container stop 0123456789ab (image=example:1, name=example)
Different filter keys combine as a logical AND. Repeating the same key is an OR, so this watches two named containers at once:
$ docker system events \
--filter 'container=web' \
--filter 'container=worker'
Useful filter keys include container, event, image, label, network, service, type and volume. The CLI also supports object types such as daemon, node, secret and config where the daemon exposes those events. Quote the complete filter, especially when the value contains spaces or shell characters.
Do not confuse an event filter with an action: --filter 'event=stop' watches for stop events, it does not stop anything. If a filter returns nothing, drop the filters first and use a short --since window to confirm the daemon is producing events at all.
5. Choose text or JSON output
The default text suits a terminal. For a stable, machine-readable stream, use the JSON template:
$ docker system events \
--since 10m \
--filter 'type=container' \
--format '{{json .}}'
{"status":"start","id":"0123456789abcdef","from":"example:1","Type":"container","Action":"start"}
Each event lands as one JSON object per line, JSON Lines. Fields vary by object and event, so consumers should tolerate fields they do not need rather than assume every event carries the same attributes. The real ID and attribute set can run longer than the sample line above.
You can also select fields for a compact human-readable line with a Go template:
$ docker system events \
--since 10m \
--filter 'type=container' \
--format 'type={{.Type}} status={{.Status}} id={{.ID}}'
type=container status=start id=0123456789abcdef
Use {{json .}} when another program parses the result, and keep a terminal-friendly template for a human incident log. Template fields are event data, not shell variables, so do not wrap them in shell expansion.
6. Diagnose gaps without guessing
Docker event history is limited. The current Docker reference documents that only the last 256 log events are returned, and filters can shrink what you see further. An old event missing from a query may simply have fallen outside the retained window rather than never having happened.
Check the client context when the output contradicts what you saw elsewhere:
$ docker context show
default
$ docker info --format '{{.ServerVersion}}'
29.8.1
Event time comes from the Docker daemon, while relative time arguments are computed from the client machine's clock. A clock mismatch can make a duration query surprising. For incident records, prefer an absolute timestamp with an explicit timezone, and record the context and daemon version alongside the output.
Do not reach for elevated privileges as a first troubleshooting step. If an unprivileged command can read docker info, it should normally read events in the same context too. If access is denied, ask the system administrator to review the daemon socket and group policy rather than copying sensitive event output into a privileged shell.
Done means
- Version confirmed. You confirmed the installed Docker CLI version and daemon context.
- Stream controlled. You can start a live stream and stop it with
Ctrl+Cwithout changing Docker state. - Window bounded. You can bound a query with
--sinceand--until, using an explicit timezone for fixed times. - Filter logic clear. You know different filter keys combine with AND, while repeated values of one key combine with OR.
- Machine output ready. You can produce JSON Lines with
--format '{{json .}}'and do not assume every event has identical fields. - History limit known. Missing old events may simply be outside the retained 256-event history, not evidence nothing happened.