Quick Links

Docker Engine records an event whenever significant actions are taken by the daemon. You can access the event log to identify when an action occurred and track changes to objects over time.

In this article, we'll explain what's captured as events and when you might want to view them. We'll then show how to monitor events in real-time using the Docker CLI and REST API.

What are Docker Events?

Docker events describe the activities taken by your Docker daemon. Most interactions with objects such as containers, images, volumes, and networks record an event, creating a log that you can use to inspect past changes.

There are many different kinds of event that identify specific changes in your environment:

  • Creating and removing containers
  • Container health check statuses
  • Commands executed inside containers with
            docker exec
        
  • Pulling and pushing images
  • Creating, destroying, mounting, and unmounting volumes
  • Enabling and disabling Docker daemon plugins

You can view the complete list in Docker's documentation.

Each recorded event includes a timestamp and the ID of the affected object. You can use this information to assemble a history of changes to your environment, whether or not you observed their original triggers.

Stored events can also help to diagnose issues such as unexpected container failures. Viewing the log lets you identify the precise time when a container stopped, providing a data point that you can correlate with your other logs. Events can establish when a container's health checks began failing, narrowing down the period of interest when you need to inspect external services to determine the root cause of a problem.

Streaming Docker Events With the Docker CLI

The docker events CLI command streams events from your Docker daemon into your terminal window. Events will appear in real-time until you terminate the process by pressing the Ctrl+C keyboard combination.

Running the command without arguments won't show any output to begin with. Only new activity is displayed so the output remains empty until an event occurs. You can provoke one by starting a new container in a different shell:

$ docker run --rm hello-world

Several events should now appear in the terminal window that's running the docker events command:

2022-05-31T15:20:00.267970018+01:00 image pull hello-world:latest (name=hello-world)

2022-05-31T15:20:00.347054862+01:00 container create 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378 (image=hello-world, name=nifty_morse)

2022-05-31T15:20:00.347805277+01:00 container attach 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378 (image=hello-world, name=nifty_morse)

2022-05-31T15:20:00.621070053+01:00 container start 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378 (image=hello-world, name=nifty_morse)

...

Each event displays on its own line. The event timestamp is displayed first, followed by the type of object affected (such as image or container) and then the action that was taken (like create, attach, and start). The remainder of the message contains useful metadata about the object. The example above reveals that the hello-world:latest image was pulled and a container created from it.

Formatting Output

The raw event list is often unwieldy. You can reformat the output using the --format flag which accepts a Go template string:

$ docker events --format '{{ .Time }} {{ .Action }} {{ .Type}} {{ .ID }}'

Running this example will produce output that looks like this:

1654006800 pull image hello-world:latest

1654006800 create container 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378

1654006800 attach container 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378

1654006800 start container 4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378

You can get events represented as JSON objects by using {{ json . }} as your template string:

$ docker events --format '{{ json . }}' | jq

{

"status": "create",

"id": "4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378",

"from": "hello-world",

"Type": "container",

"Action": "create",

"Actor": {

"ID": "4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378",

"Attributes": {

"image": "hello-world",

"name": "nifty_morse"

}

},

"scope": "local",

"time": 1654006800,

"timeNano": 1654006800347054800

}

Here the raw JSON is being passed through jq so it's pretty printed in your terminal. This makes the information easier to scan through.

When you're creating custom format strings, you can use the properties in the JSON output as a reference for supported placeholders. In most cases you'll need to capitalize the first letter of each property, such as time to {{ .Time }}.

Filtering Events

The event log for a busy Docker daemon can quickly become noisy. You can narrow the events down to a specific action, object, or type of object with the --filter flag:

  • docker events --filter type=container - Get all events that relate to containers.
  • docker events --filter event=create - Get container creation events.
  • docker events --filter container=demo-container - Get all the events saved for the container called demo-container (you can reference the container's ID or name).

Besides container, you can filter by all supported object type names such as image, network, and volume.

Multiple filters are supported when you repeat the --filter flag. Distinct filters are interpreted as logical AND conditions; multiple uses of the same filter become OR clauses. Here's an example which surfaces the create event for both the app-container and api-container containers:

$ docker events \

--filter container=app-container

--filter container=api-container

--filter event=create

Accessing Historical Events

docker events defaults to only showing events stored since the command's been running. You can include historical events by adding the --since flag. This accepts a human-readable time expression or an absolute timestamp:

$ docker events --since 1h

$ docker events --since '2021-05-01T16:00:00'

Events recorded after the given time will immediately be shown in your terminal. New events will continue to show up in real-time as they're recorded.

You can exclude events after a particular time with the --until flag. It works similarly to --since. Using --until will disable real-time streaming of new events because they'd fall outside the requested timeframe.

Streaming Docker Events From the Daemon REST API

Another way to access stored events is through the Docker daemon REST API. You can use the /events endpoint to stream events in real-time after you've enabled the API on your Docker host. Events will be returned in JSON format:

$ curl http://127.0.0.1:2375/v1.41/events

{

"Type": "container",

"Action": "create",

"Actor": {

"ID": "4a6c8d34a183363db5dbfdcc3cab4c82c4a341d719df56ec2e7f879ee8f02378",

"Attributes": {

"image": "hello-world",

"name": "nifty_morse"

}

},

"scope": "local",

"time": 1654006800,

"timeNano": 1654006800347054800

}

The API endpoint supports filter, since, and until parameters that have the same behaviors as their CLI counterparts. Here's how to retrieve all container creation events recorded in the past hour:

$ curl http://127.0.0.1:2375/v1.41/events?since=1h&filters={'type':'container','action':'create'}

Sending Events to an External Service

Docker lacks a built-in way to send events to an external service. This could be useful if you want all your container creations to be logged in an existing monitoring or auditing platform.

You can set up your own solution by creating a system service that continually runs docker events. It should send each new line of output to your external system.

First write a Bash script that implements the functionality you need:

#!/bin/bash

docker events --format '{{ .Time }} {{ .Action }} {{ .Type }} {{ .ID }}' | while read event

do

curl \

-X POST \

-H "Content-Type: application/json" \

-d '{"event": "$event"}' \

https://example.com/events

done

Now create a new systemd service unit at /etc/systemd/system/docker-events.service:

[Unit]

Description=Custom Docker Event Monitoring Service

[Service]

Type=forking

ExecStart=/usr/local/bin/docker-events.sh

[Install]

WantedBy=multi-user.target

Finally reload systemd to load your service, then start and enable the unit:

$ sudo systemctl daemon-reload

$ sudo systemctl start docker-events

$ sudo systemctl enable docker-events

Your service will now stream each new event to your monitoring platform. Enabling the service configures it to start automatically each time your host reboots.

Summary

Docker events are created whenever the daemon modifies objects in your environment. Streaming the event log lets you monitor daemon activity in real-time. This can help you debug issues, audit changes, and ensure compliance.

As events are retrieved directly from the Docker server, they shouldn't be relied upon if you'll need to retrieve information in the future. Only 1,000 entries are retained on a rolling basis and you can't access events via your Docker host's filesystem. The mechanism is best suited to quick ad-hoc tasks where you're looking for specific information related to a recent activity. For long-term retention you should use your own system service to send events to an external repository.