Docker
The Docker Infrastructure Agent is a containerized version of our Host Agent that:
- Collects host-level metrics by querying the Docker daemon via its bridge gateway.
- Reads and forwards container logs through bind-mounted volumes.
- Exposes ports for health checks and metrics scraping.
This guide walks you through installing, configuring, and verifying the Docker Infra Agent on your host.
Prerequisites
- Docker Engine v19.03+ installed and running on each host.
- cgroup memory management enabled (required to collect container metrics).
- Internet access (direct or via proxy) from the host to install.middleware.io and your <MW_UID>.middleware.io endpoint.
- *Only one Infra Agent per host (multiple agents may cause conflicts).
Installation
1 Run the Install Script
Copy and paste the command below (replace <MW_API_KEY> and <MW_TARGET>):
1MW_API_KEY="<MW_API_KEY>" \
2MW_TARGET="https://<MW_UID>.middleware.io:443" \
3bash -c "$(curl -fsSL https://install.middleware.io/scripts/docker-install.sh)"If you don’t see your API key or target, log in to the Installation page and copy the command directly.
Install with Custom Host Tags (Optional)
Attach metadata (e.g., env:prod or role:web) to filter and group hosts in the UI:
1MW_HOST_TAGS=key1:value1,key2:value2,... \
2MW_API_KEY="<MW_API_KEY>" MW_TARGET=https://<MW_UID>.middleware.io:443 \
3bash -c "$(curl -L https://install.middleware.io/scripts/docker-install.sh)"Tags appear under Infrastructure → [Your Host] → System Information in the Middleware.io UI.
2 Verify Installation
Run:
1docker ps -a --filter ancestor=ghcr.io/middleware-labs/mw-host-agent:master
- Up or Exited status means the container ran successfully.
- A blank result indicates the agent never started (check the install logs).
3 Check Your Dashboard
- Log in to https://app.middleware.io.
- Navigate to Infrastructure → Installation.
- Confirm your host appears with a recent “Last seen” timestamp (usually within 1–2 minutes).

Metrics can take a few minutes to show up. If nothing appears after 5 minutes, see Troubleshooting.
Docker Compose
To run the container with Docker Compose or to review the necessary ports, volumes, privileges, and network mode for running it, please refer to the Docker Compose file below for more details:
1version: "3.8"
2services:
3 mw-host-agent:
4 image: ghcr.io/middleware-labs/mw-host-agent:master
5 restart: unless-stopped
6 environment:
7 - MW_API_KEY=<MW_API_KEY>
8 - MW_TARGET=https://<MW_UID>.middleware.io:443
9 ports:
10 - "9319:9319"
11 - "9320:9320"
12 volumes:
13 - /var/run/docker.sock:/var/run/docker.sock:ro
14 - /proc:/host/proc:ro
15 - /sys/fs/cgroup:/host/sys/fs/cgroup:roNext, bring it up:
1docker-compose up -d
2docker-compose ps
Troubleshooting
Socket not found
1Error: no such file or directory: /var/run/docker.sockEnsure Docker is installed and the socket path hasn’t been customized (
DOCKER_HOST).Permission denied on mounts Run the install command with sudo, or adjust file permissions temporarily:
1sudo bash -c "$(curl -L https://install.middleware.io/scripts/docker-install.sh)"Metrics don’t appear in UI Confirm the following:
- Outbound port 443 is open.
- Only one Infra Agent per host/container is running.
- No corporate proxy is blocking traffic (set
HTTP_PROXY/HTTPS_PROXYif needed).
Container immediately exits:
1docker logs <container_id>
Inspect the logs for missing env vars or connectivity errors.
Uninstall
To completely remove the agent container:
1docker stop `docker ps -a -q --filter ancestor=ghcr.io/middleware-labs/mw-host-agent:master`
2
3docker rm `docker ps -a -q --filter ancestor=ghcr.io/middleware-labs/mw-host-agent:master`Collected Metrics
| Metric | Description | Shown as |
|---|---|---|
| container.blockio.io_merged_recursive | Number of bios/requests merged into requests belonging to this cgroup and its descendant cgroups (Only available with cgroups v1). | operation |
| container.blockio.io_queued_recursive | Number of requests queued up for this cgroup and its descendant cgroups (Only available with cgroups v1). | operation |
| container.blockio.io_service_bytes_recursive | Number of bytes transferred to/from the disk by the group and descendant groups. | byte |
| container.blockio.io_service_time_recursive | Total amount of time in nanoseconds between request dispatch and request completion for the IOs done by this cgroup and descendant cgroups (Only available with cgroups v1). | nanosecond |
| container.blockio.io_serviced_recursive | Number of IOs (bio) issued to the disk by the group and descendant groups (Only available with cgroups v1). | operation |
| container.blockio.io_time_recursive | Disk time allocated to cgroup (and descendant cgroups) per device in milliseconds (Only available with cgroups v1). | millisecond |
| container.blockio.io_wait_time_recursive | Total amount of time the IOs for this cgroup (and descendant cgroups) spent waiting in the scheduler queues for service (Only available with cgroups v1). | nanosecond |
| container.blockio.sectors_recursive | Number of sectors transferred to/from disk by the group and descendant groups (Only available with cgroups v1). | sector |
| container.cpu.limit (gauge) | CPU limit set for the container. | cpu core |
| container.cpu.logical.count (gauge) | Number of cores available to the container. | cpu core |
| container.cpu.shares (gauge) | CPU shares set for the container. | 1 |
| container.cpu.throttling_data.periods | Number of periods with throttling active. | period |
| container.cpu.throttling_data.throttled_periods | Number of periods when the container hits its throttling limit. | period |
| container.cpu.throttling_data.throttled_time | Aggregate time the container was throttled. | nanosecond |
| container.cpu.usage.kernelmode | Time spent by tasks of the cgroup in kernel mode (Linux). Time spent by all container processes in kernel mode (Windows). | nanosecond |
| container.cpu.usage.percpu | Per-core CPU usage by the container (Only available with cgroups v1). | nanosecond |
| container.cpu.usage.system | System CPU usage, as reported by docker. | nanosecond |
| container.cpu.usage.total | Total CPU time consumed. | nanosecond |
| container.cpu.usage.usermode | Time spent by tasks of the cgroup in user mode (Linux). Time spent by all container processes in user mode (Windows). | nanosecond |
| container.cpu.utilization (gauge) | Percent of CPU used by the container. | 1 |
| container.memory.active_anon | The amount of anonymous memory that has been identified as active by the kernel. | byte |
| container.memory.active_file | Cache memory that has been identified as active by the kernel. | byte |
| container.memory.anon | Amount of memory used in anonymous mappings such as brk(), sbrk(), and mmap(MAP_ANONYMOUS) (Only available with cgroups v2). | byte |
| container.memory.cache | The amount of memory used by the processes of this control group that can be associated precisely with a block on a block device (Only available with cgroups v1). | byte |
| container.memory.dirty | Bytes that are waiting to get written back to the disk, from this cgroup (Only available with cgroups v1). | byte |
| container.memory.fails | Number of times the memory limit was hit. | failure |
| container.memory.file | Amount of memory used to cache filesystem data, including tmpfs and shared memory (Only available with cgroups v2). | byte |
| container.memory.hierarchical_memory_limit | The maximum amount of physical memory that can be used by the processes of this control group (Only available with cgroups v1). | byte |
| container.memory.hierarchical_memsw_limit | The maximum amount of RAM + swap that can be used by the processes of this control group (Only available with cgroups v1). | byte |
| container.memory.inactive_anon | The amount of anonymous memory that has been identified as inactive by the kernel. | byte |
| container.memory.inactive_file | Cache memory that has been identified as inactive by the kernel. | byte |
| container.memory.mapped_file | Indicates the amount of memory mapped by the processes in the control group (Only available with cgroups v1). | byte |
| container.memory.percent (gauge) | Percentage of memory used. | 1 |
| container.memory.pgfault | Indicate the number of times that a process of the cgroup triggered a page fault. | fault |
| container.memory.pgmajfault | Indicate the number of times that a process of the cgroup triggered a major fault. | fault |
| container.memory.pgpgin | Number of pages read from disk by the cgroup (Only available with cgroups v1). | operation |
| container.memory.pgpgout | Number of pages written to disk by the cgroup (Only available with cgroups v1). | operation |
| container.memory.rss | The amount of memory that doesn't correspond to anything on disk: stacks, heaps, and anonymous memory maps (Only available with cgroups v1). | byte |
| container.memory.rss_huge | Number of bytes of anonymous transparent hugepages in this cgroup (Only available with cgroups v1). | byte |
| container.memory.total_active_anon | The amount of anonymous memory that has been identified as active by the kernel. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_active_file | Cache memory that has been identified as active by the kernel. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_cache | Total amount of memory used by the processes of this cgroup (and descendants) that can be associated with a block on a block device. Also accounts for memory used by tmpfs (Only available with cgroups v1). | byte |
| container.memory.total_dirty | Bytes that are waiting to get written back to the disk, from this cgroup and descendants (Only available with cgroups v1). | byte |
| container.memory.total_inactive_anon | The amount of anonymous memory that has been identified as inactive by the kernel. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_inactive_file | Cache memory that has been identified as inactive by the kernel. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_mapped_file | Indicates the amount of memory mapped by the processes in the control group and descendant groups (Only available with cgroups v1). | byte |
| container.memory.total_pgfault | Indicate the number of times that a process of the cgroup (or descendant cgroups) triggered a page fault (Only available with cgroups v1). | fault |
| container.memory.total_pgmajfault | Indicate the number of times that a process of the cgroup (or descendant cgroups) triggered a major fault (Only available with cgroups v1). | fault |
| container.memory.total_pgpgin | Number of pages read from disk by the cgroup and descendant groups (Only available with cgroups v1). | operation |
| container.memory.total_pgpgout | Number of pages written to disk by the cgroup and descendant groups (Only available with cgroups v1). | operation |
| container.memory.total_rss | The amount of memory that doesn't correspond to anything on disk: stacks, heaps, and anonymous memory maps. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_rss_huge | Number of bytes of anonymous transparent hugepages in this cgroup and descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_unevictable | The amount of memory that cannot be reclaimed. Includes descendant cgroups (Only available with cgroups v1). | byte |
| container.memory.total_writeback | Number of bytes of file/anon cache that are queued for syncing to disk in this cgroup and descendants (Only available with cgroups v1). | byte |
| container.memory.unevictable | The amount of memory that cannot be reclaimed. | byte |
| container.memory.usage.limit | Memory limit of the container. | byte |
| container.memory.usage.max | Maximum memory usage. | byte |
| container.memory.usage.total | Memory usage of the container. This excludes the cache. | byte |
| container.memory.writeback | Number of bytes of file/anon cache that are queued for syncing to disk in this cgroup (Only available with cgroups v1). | byte |
| container.network.io.usage.rx_bytes | Bytes received by the container. | byte |
| container.network.io.usage.rx_dropped | Incoming packets dropped. | packets |
| container.network.io.usage.rx_errors | Received errors. | error |
| container.network.io.usage.rx_packets | Packets received. | packets |
| container.network.io.usage.tx_bytes | Bytes sent. | byte |
| container.network.io.usage.tx_dropped | Outgoing packets dropped. | packets |
| container.network.io.usage.tx_errors | Sent errors. | error |
| container.network.io.usage.tx_packets | Packets sent. | packets |
| container.pids.count | Number of pids in the container's cgroup. | process id |
| container.pids.limit | Maximum number of pids in the container's cgroup. | process id |
| container.restarts | Number of restarts for the container. | restart |
| container.status (gauge) | Container Status => 0-created 1-running 2-paused 3-restarting 4-removing 5-exited 6-dead | count |
| container.uptime (gauge) | Time elapsed since container start time. | second |
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.