All posts

Self-hosting chmonitor on Docker in five minutes

Run the chmonitor ClickHouse dashboard as a self-hosted Docker container against your own cluster, no signup or cloud account required.

This is for anyone who wants a ClickHouse dashboard running against their own cluster without handing credentials to a third party. chmonitor’s Docker image is the same codebase as the hosted Cloud product — self-hosted just means you run the container yourself. By the end you’ll have it up on localhost:3000 and pointed at a real cluster.

Prerequisites

Steps

1. Pull and run

docker run -d --name chmonitor -p 3000:3000 \
  --add-host=host.docker.internal:host-gateway \
  -e CLICKHOUSE_HOST='http://host.docker.internal:8123' \
  -e CLICKHOUSE_USER='monitoring' \
  -e CLICKHOUSE_PASSWORD='change-me' \
  ghcr.io/chmonitor/chmonitor:vX.Y.Z

Replace vX.Y.Z with a real release tag. The --add-host flag is only needed on Linux, when ClickHouse runs on the same Docker host — Docker Desktop for Mac/Windows already resolves host.docker.internal without it.

Open http://localhost:3000.

2. Or use Docker Compose

services:
  chmonitor:
    image: ghcr.io/chmonitor/chmonitor:vX.Y.Z
    ports:
      - '3000:3000'
    environment:
      CLICKHOUSE_HOST: 'http://clickhouse:8123'
      CLICKHOUSE_USER: 'monitoring'
      CLICKHOUSE_PASSWORD: 'change-me'
    healthcheck:
      test: ['CMD', 'wget', '-q', '-O', '/dev/null', 'http://localhost:3000/api/health']
      interval: 30s
      timeout: 5s
      start_period: 20s
      retries: 3

If ClickHouse runs in the same Compose project, use the service name (clickhouse above) as the host directly — no host.docker.internal needed.

3. Point it at more than one host (optional)

CLICKHOUSE_HOST accepts a comma-separated list; CLICKHOUSE_USER and CLICKHOUSE_PASSWORD can each be a single value applied to every host, or one value per position:

-e CLICKHOUSE_HOST='http://ch1:8123,http://ch2:8123' \
-e CLICKHOUSE_USER='monitoring,monitoring' \
-e CLICKHOUSE_PASSWORD='pass1,pass2' \
-e CLICKHOUSE_NAME='shard-1,shard-2'

4. Adjust query timeouts and pool size (optional)

-e CLICKHOUSE_MAX_EXECUTION_TIME='30' \
-e CLICKHOUSE_POOL_SIZE='10'

Defaults are a 60s query timeout and a pool size of 10 — raise the timeout if your workload has legitimately slow diagnostic queries, or the pool size if many people are hitting the dashboard concurrently.

Verifying it worked

curl -sf http://localhost:3000/api/healthz && echo OK

/api/healthz is the readiness probe — it checks the container is up and that it can reach ClickHouse, so a green result here means the whole path is working, not just that the container started.