Docker Container Monitoring in Uptime Kuma: Architecture and Implementation Guide

Uptime Kuma monitors Docker containers by connecting directly to the Docker daemon via Unix sockets or TCP endpoints, querying container state through the Docker API, and translating health status into UP, DOWN, or PENDING monitor states.

Uptime Kuma provides native Docker container monitoring that interfaces directly with the Docker daemon to track container health beyond simple process checks. This feature allows you to monitor container state, health check results, and runtime status through either local Unix sockets or remote TCP connections. Understanding how this mechanism works requires examining the interaction between the frontend Docker host management UI, the backend Docker helper utilities, and the monitor execution engine.

Architecture of Docker Container Monitoring

The Docker container monitoring system in Uptime Kuma operates across three distinct layers that handle host configuration, connection management, and health evaluation.

Frontend to Backend Communication

The configuration layer manages Docker host registration through Socket.io events. When you add a Docker host via the settings interface (src/components/settings/Docker.vue), the frontend emits the addDockerHost event handled by server/socket-handlers/docker-socket-handler.js. This handler persists host details—including socket paths or TCP endpoints—to the docker_host table via DockerHost.save.

Docker Host Helper Layer

The server/docker.js module provides core utilities for Docker daemon interaction. It handles connection testing through DockerHost.testDockerHost, which queries /containers/json?all=true to verify connectivity, and builds appropriate Axios configurations for both Unix socket (options.socketPath) and TCP (options.baseURL) connections. For TCP connections, it manages TLS certificate handling through DockerHost.getHttpsAgentOptions and URL normalization via DockerHost.patchDockerURL.

Monitor Execution Engine

When a monitor of type docker executes within server/model/monitor.js (lines 1414–1488), it loads the associated Docker host record and constructs an API request to GET /containers/<container-id>/json. The response parsing logic evaluates container state to determine monitor status.

Configuring Docker Hosts for Monitoring

Before creating container monitors, you must register Docker hosts through the Uptime Kuma settings interface.

Adding and Testing Docker Hosts

The system supports two connection types: Unix sockets for local daemons and TCP endpoints for remote hosts. To verify connectivity, the testDockerHost function attempts to list all containers:

// Example: Testing Docker host connectivity via Socket.io
socket.emit('testDockerHost', {
    name: 'Production Docker Host',
    dockerDaemon: 'tcp://192.168.1.100:2376',
    dockerType: 'tcp'
}, (result) => {
    if (result.ok) {
        console.log('Connection successful. Containers found:', result.msg);
    } else {
        console.error('Test failed:', result.msg);
    }
});

Connection Security and TLS

For TCP connections, Uptime Kuma constructs HTTPS agents with configurable TLS verification. The DockerHost.getHttpsAgentOptions method generates TLS configuration based on host settings, respecting the monitor's ignoreTls flag to handle self-signed certificates in development environments.

How Container Health Checks Execute

The core monitoring logic resides in server/model/monitor.js within the Docker-specific execution branch.

API Request Construction

During each monitoring interval, the system builds an Axios request targeting the Docker daemon. For socket connections, it sets socketPath to the Unix socket file path. For TCP connections, it configures baseURL and attaches the HTTPS agent:

// Simplified excerpt from Monitor.start (server/model/monitor.js)
const dockerHost = await R.load("docker_host", this.docker_host);
const options = {
    url: `/containers/${this.docker_container}/json`,
    timeout: this.interval * 1000 * 0.8,
    headers: { Accept: '*/*' }
};

if (dockerHost._dockerType === "socket") {
    options.socketPath = dockerHost._dockerDaemon;
} else {
    options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon);
    options.httpsAgent = new https.Agent(
        await DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL)
    );
}

const res = await axios.request(options);

State Evaluation Logic

The monitor parses the JSON response from the Docker API to determine container status using the following rules:

  • Running State: If res.data.State.Running is true and no health check is configured, the monitor reports UP
  • Paused State: If State.Paused is true, the monitor throws an error and reports DOWN
  • Restarting State: If State.Restarting is true, the monitor sets status to PENDING with a restart notification
  • Health Check Results: When State.Health exists:
    • healthy → UP
    • unhealthy → DOWN
    • Any other status (starting, etc.) → PENDING

Database Schema and Monitor Configuration

Docker monitors require specific database entries linking them to Docker hosts. The monitor table stores the container identifier in docker_container and references the host via docker_host:

INSERT INTO monitor (
    name, type, docker_host, docker_container, interval, user_id
) VALUES (
    'Nginx Container',
    'docker',
    1,                      -- Reference to docker_host.id
    'nginx-proxy',          -- Container name or ID
    60,
    1
);

Summary

  • Uptime Kuma implements Docker container monitoring through direct Docker API communication using Axios, supporting both Unix sockets and TCP endpoints with TLS authentication
  • The server/docker.js module provides host management utilities including DockerHost.testDockerHost for connectivity verification and TLS agent configuration
  • Monitor execution occurs in server/model/monitor.js (lines 1414–1488), where the system queries /containers/<id>/json and evaluates State.Running, State.Paused, and State.Health to determine status
  • Health status mapping follows specific rules: running containers without health checks report UP, paused containers report DOWN, restarting containers report PENDING, and explicit health checks override the running state
  • Configuration persists in the docker_host table, managed through Socket.io handlers in server/socket-handlers/docker-socket-handler.js

Frequently Asked Questions

Does Uptime Kuma require the Docker socket to be mounted for container monitoring?

Yes. To monitor Docker containers, Uptime Kuma must access the Docker daemon either through a mounted Unix socket (typically /var/run/docker.sock) or via a TCP endpoint. When using the socket method, ensure the Uptime Kuma container has the socket volume-mounted with appropriate permissions. For remote hosts, configure TCP access in the Docker daemon settings and register the endpoint in Uptime Kuma's Docker host settings.

What is the difference between a container being "Running" and "Healthy" in Uptime Kuma?

A container in "Running" state has an active process but may not have completed startup or passed application-specific health checks. Uptime Kuma reports these as UP unless the container defines a HEALTHCHECK instruction in its Dockerfile. When health checks are configured, Uptime Kuma prioritizes the State.Health.Status field: "healthy" means UP, "unhealthy" means DOWN, and intermediate states like "starting" result in PENDING status.

How does Uptime Kuma handle Docker daemon connection failures?

If the Docker daemon is unreachable during a monitoring interval, the Axios request in server/model/monitor.js throws a connection error that propagates to the monitor's heartbeat logic. This results in a DOWN status for the monitor, with the error message containing the specific connection failure details (timeout, ECONNREFUSED, or TLS errors). The system does not cache previous states; each check requires successful API communication.

Can Uptime Kuma monitor containers on multiple remote Docker hosts simultaneously?

Yes. Uptime Kuma supports configuring multiple Docker hosts through the docker_host table, each with distinct connection parameters. You create separate monitor records for each container, specifying the appropriate docker_host ID for each. The monitor execution engine loads the specific host configuration via R.load("docker_host", this.docker_host), allowing simultaneous monitoring of containers across different servers or clusters.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →