Skip to content

Docker metrics reference (ARM64 + cgroup v2) ​

docker-exporter exposes per-container CPU, memory, network, disk I/O, state, and health as Prometheus text at /metrics — including container_memory_working_set_bytes, computed the way docker stats does on cgroup v1 and v2. Metric names are cAdvisor-compatible, so most existing Grafana dashboards work unchanged.

All per-container metrics carry the base labels id, image, and name. Some add extra labels, noted below.

Resource series (CPU, memory, network, block I/O) exist only when Docker returns a stats sample. A stopped container, a failed or timed-out fetch, and a container caught mid-restart have none for that scrape: they keep their state, health and lifecycle series, and their resource series are absent. Absent, never 0: a zero would read as an idle container, and on the cumulative CPU counter as a reset.

Exporter ​

MetricTypeLabelsDescription
docker_exporter_upgauge—Docker daemon reachable (1 = up, 0 = down).
docker_exporter_scrape_duration_secondsgauge—Duration of the last scrape, in seconds.
docker_exporter_inspect_failures_totalcounter—Total container-inspect failures since start.
docker_exporter_stats_failures_totalcounter—Total container-stats fetch failures since start.

Alert on both failure counters. docker_exporter_up only tells you the daemon answered the container list, so a scrape can be up while some containers went unread. When an inspect fails, that container's health reads none and its restart_policy reads unknown. When a stats fetch fails, its resource series are absent from that scrape: a gap in the graph, which the counter explains.

promql
rate(docker_exporter_inspect_failures_total[5m]) > 0
rate(docker_exporter_stats_failures_total[5m]) > 0

CPU ​

MetricTypeLabelsDescription
container_cpu_usage_seconds_totalcounterid, image, nameCumulative CPU usage in seconds.

Memory ​

MetricTypeLabelsDescription
container_memory_usage_bytesgaugeid, image, nameCurrent memory usage in bytes (includes cache).
container_memory_working_set_bytesgaugeid, image, nameWorking set: usage − inactive_file (v2), usage − cache (v1).
container_memory_cachegaugeid, image, nameCache: inactive_file (v2), cache (v1).
container_memory_limit_bytesgaugeid, image, nameMemory limit in bytes.

container_memory_working_set_bytes matches what docker stats reports. It reads zero only when the host isn't accounting memory, which is the Raspberry Pi default: enable memory cgroups →

See the full docker-exporter vs. cAdvisor comparison → for footprint and metric-coverage differences.

Network ​

MetricTypeLabelsDescription
container_network_receive_bytes_totalcounterid, image, name, interfaceCumulative network bytes received.
container_network_transmit_bytes_totalcounterid, image, name, interfaceCumulative network bytes transmitted.

Disk I/O ​

MetricTypeLabelsDescription
container_blkio_device_usage_totalcounterid, image, name, operationCumulative block I/O bytes (operation = read/write).

Block I/O metrics emit only after a container reports non-zero bytes — containers that never touch disk produce no blkio series, keeping cardinality down.

State, health & lifecycle ​

MetricTypeLabelsDescription
container_stategaugeid, image, name, state, restart_policy1 if state == "running", 0 otherwise.
container_exit_codegaugeid, image, name, restart_policyExit code of a container in a terminal state (exited/dead).
container_health_statusgaugeid, image, name, status1 for the container's current health status.
container_start_time_secondsgaugeid, image, nameWhen the container last started, as a Unix timestamp.
container_creation_time_secondsgaugeid, image, nameWhen the container was created, as a Unix timestamp.
container_last_seengaugeid, image, nameLast scrape time as a Unix timestamp.
  • restart_policy lives only on container_state and container_exit_code — adding it to every family would multiply series counts for no benefit. It lets alerting exclude one-shot containers by label — e.g. select container_state{restart_policy!="no"} in a ContainerStopped alert instead of maintaining a name denylist.
  • container_exit_code is the failure signal for one-shot containers (restart: "no" migrations, batch jobs). container_state collapses to 0 for anything not running and cannot tell Exited(0) from Exited(1), so a job that ran and failed looks exactly like one that ran and succeeded. The value is the raw code — 137 (OOM/SIGKILL), 1, 78 — because the number is the diagnosis.
    • Emitted only for exited/dead containers. A running container's inspect reports ExitCode: 0, and a created one has never run; publishing either would read as "succeeded".
    • Absent, never 0, when the inspect fails — the exporter has no exit code to report and will not invent one. docker_exporter_inspect_failures_total is the signal for that case.
    • The series appears when a one-shot finishes and disappears when the container is replaced, so container_exit_code{restart_policy="no"} != 0 resolves on redeploy.
  • container_health_status emits one series per container, with status set to the current Docker health (healthy, unhealthy, starting, or none when the container has no HEALTHCHECK).
  • container_start_time_seconds is Docker's State.StartedAt, so it moves on every start, manual docker restart included, and changes() over it counts restarts. A container that never started reports its creation time, as cAdvisor does.
    • Absent when the inspect fails. Falling back to the creation time would flip the series and back, which changes() would count as two restarts.
    • Up to v1.5.4 this metric carried the creation time. That value now lives in container_creation_time_seconds, which never moves; cAdvisor splits the two the same way.

Endpoints ​

PathDescription
/metricsPrometheus exposition (text/plain; version=0.0.4; charset=utf-8).
/healthLiveness — 200 ok if the Docker daemon is reachable.
/readyReadiness — 200 ready if the Docker daemon is reachable.

The image ships a HEALTHCHECK that runs the binary's built-in --health flag — a lightweight TCP liveness probe against its own listening port (no shell or wget, so it works on distroless) — so docker ps shows health out of the box. That probe only confirms the HTTP server is accepting connections; the /health endpoint additionally pings the Docker daemon and returns 503 if it is unreachable.

Sample output ​

Trimmed to a few lines, container names anonymized:

text
# HELP docker_exporter_up Whether the Docker daemon is reachable (1 = up, 0 = down)
# TYPE docker_exporter_up gauge
docker_exporter_up 1
# TYPE docker_exporter_scrape_duration_seconds gauge
docker_exporter_scrape_duration_seconds 2.18
# TYPE container_cpu_usage_seconds_total counter
container_cpu_usage_seconds_total{id="abc...",image="nginx:alpine",name="web-app"} 145.26
# TYPE container_memory_working_set_bytes gauge
container_memory_working_set_bytes{id="abc...",image="nginx:alpine",name="web-app"} 37371904
# TYPE container_state gauge
container_state{id="abc...",image="nginx:alpine",name="web-app",state="running",restart_policy="unless-stopped"} 1
# TYPE container_exit_code gauge
container_exit_code{id="def...",image="myapp/migrate:1.4",name="db-migrate",restart_policy="no"} 1
# TYPE container_health_status gauge
container_health_status{id="abc...",image="nginx:alpine",name="web-app",status="healthy"} 1

Stability ​

Metric names and labels follow SemVer. Any breaking change to a metric name or label requires a major version bump — none are planned.

Next ​