Info
License: Free — part of the universal collection tier.
Docker¶
The docker probe monitors Docker containers via the Docker Engine API Unix
socket, reporting per-container CPU, memory, network I/O, block I/O and
running state. No external client library is required.
Quick start¶
# probes.d/10-docker.yaml — each file under probes.d/ is a YAML array of probes
- name: docker
type: docker
The probe connects to the local Docker Engine on whichever transport the platform offers, with no parameter needed for a local setup:
| Platform | Default address | Transport |
|---|---|---|
| Linux, macOS | /var/run/docker.sock |
Unix socket |
| Windows | npipe://./pipe/docker_engine |
named pipe |
Docker Engine and Docker Desktop on Windows expose the API over a named pipe
rather than a socket, which is why the default differs. Set socket_path
to override it; a Windows pipe may be written npipe://./pipe/<name> or
\\.\pipe\<name>.
Parameters¶
| Parameter | Must set | Default | Description |
|---|---|---|---|
socket_path |
No | - | Engine socket; /var/run/docker.sock on Unix, npipe://./pipe/docker_engine on Windows by default |
interval |
No | 60 |
Seconds between collections |
timeout |
No | 10 |
Engine request timeout in seconds |
include |
No | - | Container name patterns to keep; empty means all. Example: web-* |
exclude |
No | - | Container name patterns to drop; wins over include |
include and exclude are shell-style globs (web-*, db?) matched against
the container's primary name.
Metrics¶
| Metric | Unit | Description |
|---|---|---|
senhub.docker.up |
1 | 1 when the container is in the running state, 0 otherwise |
container.restarts |
{restart} | Number of times the container has been restarted |
container.cpu.usage.total |
s | Total CPU time consumed by the container (monotonic) |
container.memory.usage |
By | Current memory usage (RSS) |
senhub.docker.memory.limit |
By | Memory limit configured for the container |
container.network.io.usage.rx_bytes |
By | Bytes received on all network interfaces (monotonic) |
container.network.io.usage.tx_bytes |
By | Bytes sent on all network interfaces (monotonic) |
container.blockio.io_service_bytes_recursive.read |
By | Bytes read from block devices (monotonic) |
container.blockio.io_service_bytes_recursive.write |
By | Bytes written to block devices (monotonic) |
Each metric is tagged with container_name and container_id; CPU metrics are
additionally tagged with core.
What a Windows container reports¶
The engine answers a different shape on Windows, so a few channels come from different fields there and a few are absent:
| Channel | Linux | Windows |
|---|---|---|
| Memory usage | cgroup usage, minus the page cache for the working set | private working set, plus the commit charge and its peak |
| Memory limit | the cgroup limit | not reported by the engine, so zero |
| CPU percentage | container time against host time | container time against the wall time between two samples, times the processors the container may use |
| Block I/O | blkio counters per device |
the storage counters the engine reports for the container |
| Per-core CPU, throttling, page-cache breakdown | reported | not reported by the engine |
A value the engine does not send is left at zero rather than guessed.
Running without access to the Docker socket¶
/var/run/docker.sock is root:docker mode 0660, so an agent running as the
unprivileged senhub service user cannot open it. The usual remedy is to add
that user to the docker group — and it is worth knowing what that grants:
anyone who can reach the socket can start a container that mounts the host
filesystem, so docker group membership is root on the host by another
route. It is a decision to make deliberately, which is why the installer never
makes it for you.
The probe does not require it. When the socket is unavailable it reads container counters straight from cgroups, which are world-readable:
| Available from cgroups | Needs the socket |
|---|---|
container.cpu.* |
container.network.* |
container.memory.* |
container.restarts |
container.blockio.* |
container name, image, labels, state |
container.pids.count |
the container entity in topology |
That is 26 of the probe's 31 metrics with no group, no capability and no path to root. Containers are identified by id alone in this mode — a name guessed from a cgroup path would be wrong the moment someone renamed a container, and wrong identity is worse than none.
Per-container network counters are the real loss. They live in the container's network namespace rather than its cgroup, so there is no unprivileged file to read; they are absent rather than reported as zero.
senhub.docker.source tells you which mode a cycle used, socket or cgroup.
Alert on it if you rely on the socket-only metrics — the two modes do not carry
the same fields, and a host that quietly fell back would otherwise look like a
host whose containers stopped using the network.
Limitations: the fallback reads cgroup v2 only. On a cgroup v1 host the probe still needs the socket, and says so in the log rather than publishing half the picture.
Keeping the metadata without granting host root¶
A docker socket proxy — a small HAProxy in front of the socket that
allow-lists only the endpoints the agent reads and returns 403 for everything
else — gives the container names and labels back without granting container
creation. The probe uses exactly two read-only endpoints,
GET /containers/json and GET /containers/{id}/stats, so the allow-list is
short. Tecnativa/docker-socket-proxy
is the usual implementation.
Operational notes¶
- The agent must have read access to
/var/run/docker.sock. On Linux, add the agent user to thedockergroup or run as root. - All containers visible to the socket are monitored; use Docker labels or external filtering to restrict if needed. In cgroup mode every container with a cgroup is reported, and
include/excludecannot filter by name because no name is available. - Stopped containers emit
senhub.docker.up=0without CPU/memory metrics.
Metric reference¶
Every metric this probe can emit. Metric is the OpenTelemetry name the
OTLP, Prometheus and Zabbix outputs derive theirs from. Name is what a
Nagios check and the API metrics= filter match.
PRTG channel is the label PRTG shows, placeholders filled from the
series' tags.
| Metric | Name | PRTG channel | Unit | Description |
|---|---|---|---|---|
senhub.docker.source |
senhub.docker.source |
Docker Metric Source ({source}) | # | one-hot over socket / cgroup — which source produced this cycle. The cgroup fallback works without the docker group but reports no per-container network counters, restart counts or container names |
senhub.docker.up |
senhub.docker.up |
Docker {container_name} Up | # | 1 when the container is running, 0 otherwise |
container.restarts |
container.restarts |
Docker {container_name} Restart Count | # | Number of times the container has been restarted |
container.cpu.usage.total |
container.cpu.usage.total |
Docker {container_name} CPU Usage | ns | Cumulative CPU time consumed by the container |
container.cpu.usage.kernelmode |
container.cpu.usage.kernelmode |
Docker {container_name} CPU Kernel Mode | ns | Cumulative CPU time consumed in kernel mode by the container |
container.cpu.usage.usermode |
container.cpu.usage.usermode |
Docker {container_name} CPU User Mode | ns | Cumulative CPU time consumed in user mode by the container |
senhub.docker.cpu.system |
senhub.docker.cpu.system |
Docker {container_name} CPU System Time | ns | System CPU time since the container started (used to compute CPU %) |
senhub.docker.cpu.online |
senhub.docker.cpu.online |
Docker {container_name} CPU Online | # | Number of online CPUs available to the container |
senhub.docker.cpu.percent |
senhub.docker.cpu.percent |
Docker {container_name} CPU % | % | CPU utilisation percentage (same formula as docker stats) |
container.cpu.usage.percpu |
container.cpu.usage.percpu |
Docker {container_name} CPU Core {core} | ns | Cumulative CPU time consumed by the container on a specific core (percpu_usage) |
container.cpu.throttling_data.throttled_periods |
container.cpu.throttling_data.throttled_periods |
Docker {container_name} CPU Throttled Periods | # | Number of periods where the container was throttled (from throttling_data) |
container.cpu.throttling_data.periods |
container.cpu.throttling_data.periods |
Docker {container_name} CPU Throttling Periods | # | Total number of CPU periods (from throttling_data.throttling_periods) |
container.cpu.throttling_data.throttled_time |
container.cpu.throttling_data.throttled_time |
Docker {container_name} CPU Throttled Time | ns | Cumulative nanoseconds the container was throttled (from throttling_data) |
container.memory.usage |
container.memory.usage |
Docker {container_name} Memory Usage | B | Current memory usage of the container (includes page cache) |
senhub.docker.memory.limit |
senhub.docker.memory.limit |
Docker {container_name} Memory Limit | B | Memory limit configured for the container (0 = unlimited) |
container.memory.rss |
container.memory.rss |
Docker {container_name} Memory RSS | B | Anonymous memory (RSS on cgroupsv1, anon on cgroupsv2) |
container.memory.cache |
container.memory.cache |
Docker {container_name} Memory Cache | B | Page cache memory (cache on cgroupsv1, file on cgroupsv2) |
container.memory.swap |
container.memory.swap |
Docker {container_name} Memory Swap | B | Swap memory usage |
container.memory.working_set |
senhub.docker.memory.working_set |
Docker {container_name} Memory Working Set | B | Working set memory (usage minus page cache) — what docker stats reports as MEM USAGE |
container.memory.anon |
container.memory.anon |
Docker {container_name} Memory Anonymous | B | Anonymous (non-file-backed) memory; uses rss key on cgroupsv1, anon on cgroupsv2 |
container.memory.mapped_file |
container.memory.mapped_file |
Docker {container_name} Memory Mapped File | B | Memory mapped to files (cgroupsv1 mapped_file; absent on cgroupsv2) |
container.memory.pgfault |
container.memory.pgfault |
Docker {container_name} Memory Page Faults | # | Cumulative minor page faults (pgfault from memory_stats.stats) |
container.memory.pgmajfault |
container.memory.pgmajfault |
Docker {container_name} Memory Major Page Faults | # | Cumulative major page faults requiring disk I/O (pgmajfault from memory_stats.stats) |
container.memory.unevictable |
container.memory.unevictable |
Docker {container_name} Memory Unevictable | B | Memory that cannot be reclaimed (locked pages, mlocked regions) |
container.memory.writeback |
container.memory.writeback |
Docker {container_name} Memory Writeback | B | Memory queued for write-back to disk |
container.memory.hierarchical_memory_limit |
container.memory.hierarchical_memory_limit |
Docker {container_name} Memory Hierarchical Limit | B | Memory limit of the container's cgroup hierarchy (cgroupsv1 only) |
container.memory.active_anon |
container.memory.active_anon |
Docker {container_name} Memory Active Anon | B | Recently-accessed anonymous memory in the active LRU list |
container.memory.inactive_anon |
container.memory.inactive_anon |
Docker {container_name} Memory Inactive Anon | B | Less-recently-accessed anonymous memory in the inactive LRU list |
container.memory.active_file |
container.memory.active_file |
Docker {container_name} Memory Active File | B | Recently-accessed file-backed memory in the active LRU list |
container.memory.inactive_file |
container.memory.inactive_file |
Docker {container_name} Memory Inactive File | B | Less-recently-accessed file-backed memory in the inactive LRU list (used for working-set on cgroupsv2) |
container.pids.count |
container.pids.count |
Docker {container_name} PID Count | # | Number of processes running inside the container |
senhub.docker.pids.limit |
senhub.docker.pids.limit |
Docker {container_name} PID Limit | # | Maximum number of processes allowed in the container (0 = unlimited) |
container.network.io.usage.tx_bytes |
container.network.io.usage.tx_bytes |
Docker {container_name} Network TX | B | Cumulative bytes transmitted across all network interfaces |
container.network.io.usage.rx_bytes |
container.network.io.usage.rx_bytes |
Docker {container_name} Network RX | B | Cumulative bytes received across all network interfaces |
senhub.docker.network.tx_packets |
senhub.docker.network.tx_packets |
Docker {container_name} Network TX Packets | # | Cumulative packets transmitted across all network interfaces |
senhub.docker.network.rx_packets |
senhub.docker.network.rx_packets |
Docker {container_name} Network RX Packets | # | Cumulative packets received across all network interfaces |
container.network.io.usage.tx_errors |
container.network.io.usage.tx_errors |
Docker {container_name} Network TX Errors | # | Cumulative transmit errors across all network interfaces |
container.network.io.usage.rx_errors |
container.network.io.usage.rx_errors |
Docker {container_name} Network RX Errors | # | Cumulative receive errors across all network interfaces |
senhub.docker.network.tx_dropped |
senhub.docker.network.tx_dropped |
Docker {container_name} Network TX Dropped | # | Cumulative transmitted packets dropped across all network interfaces |
senhub.docker.network.rx_dropped |
senhub.docker.network.rx_dropped |
Docker {container_name} Network RX Dropped | # | Cumulative received packets dropped across all network interfaces |
container.blockio.usage.total |
container.blockio.usage.total |
Docker {container_name} Block I/O | B | Cumulative block I/O bytes (read + write, or Total entry when present) |
container.blockio.io_service_bytes_recursive.read |
container.blockio.io_service_bytes_recursive.read |
Docker {container_name} Block I/O Read | B | Cumulative block I/O read bytes |
container.blockio.io_service_bytes_recursive.write |
container.blockio.io_service_bytes_recursive.write |
Docker {container_name} Block I/O Write | B | Cumulative block I/O write bytes |
senhub.docker.blkio.service_time.total |
senhub.docker.blkio.service_time.total |
Docker {container_name} Block I/O Service Time | ns | Cumulative block I/O service time in nanoseconds (io_service_time_recursive Total; cgroupsv1 only) |
senhub.docker.blkio.sectors.total |
senhub.docker.blkio.sectors.total |
Docker {container_name} Block I/O Sectors | # | Cumulative block I/O sectors transferred (io_sectors_recursive Total; cgroupsv1 only) |