Docker Compose Agent
Add the KubeWatch agent to an existing Docker Compose stack.
If your application is already managed with Docker Compose, the easiest way to add KubeWatch monitoring is to append the agent service to your existing docker-compose.yml.
Add the agent service
Append the following to the services: block in your docker-compose.yml:
services:
# ... your existing services ...
kubewatch-agent:
container_name: kubewatch-agent # required for one-click self-update; see note below
image: ghcr.io/lloyd-theophilus/kubewatch-agent:latest
restart: unless-stopped
environment:
KUBEWATCH_SERVER_URL: "https://your-kubewatch-host" # your dashboard/gateway
KUBEWATCH_API_KEY: "${KUBEWATCH_API_KEY}"
KUBEWATCH_AGENT_NAME: "my-stack"
group_add:
- "${DOCKER_GID:-999}" # host docker group; see "Docker socket permissions"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- kubewatch-agent-data:/data
- /proc:/host/proc:ro
- /:/host/root:ro
volumes:
kubewatch-agent-data:
Set KUBEWATCH_SERVER_URL to your KubeWatch host: https://your-domain (or http://<ip> for a bare-IP self-hosted install). For KubeWatch Cloud, leave KUBEWATCH_SERVER_URL unset, since the agent ships with the hosted endpoint built in. The agent mounts the Docker socket read-only and only lists container state (name, image, status, ports). It doesn't write to the socket.
Persist agent state (the /data volume)
The kubewatch-agent-data:/data volume is required, not optional. The agent stores its identity (agent ID and token) in /data/agent-state.json after it first registers. With the volume:
- the agent keeps the same identity across restarts and upgrades, and
- any metrics buffered during a brief outage are replayed once the connection returns.
Without a persistent /data volume, the agent re-registers on every restart, which creates duplicate agent entries in your dashboard and loses the buffer. If you see the log line could not save state to /data/agent-state.json, the volume is missing or not writable. Add the volume shown above and recreate the container:
docker compose up -d --force-recreate kubewatch-agent
Host-level metrics (the /host/proc and /host/root mounts)
The /proc:/host/proc:ro and /:/host/root:ro mounts are optional, unlike /data above. They let the agent read this host's own system-level stats (load average, memory/swap, CPU utilization, disk throughput, filesystem usage, uptime) for the Overview page's Host Metrics dashboard.
Without them, everything else keeps working exactly as before. The agent just can't collect this host's own stats, and it logs a repeating line like:
host metrics collection error: open /host/proc/net/dev: no such file or directory
That line is expected and harmless if you don't need the Host Metrics dashboard for this host. To enable it, add both mounts and recreate the container:
docker compose up -d --force-recreate kubewatch-agent
Store the settings in .env
Create a .env file in the same directory as your docker-compose.yml. This one command fills in your key, server URL, and the host's docker GID automatically:
printf 'KUBEWATCH_API_KEY=%s\nKUBEWATCH_SERVER_URL=%s\nDOCKER_GID=%s\n' \
"kw_live_abc123..." "https://your-kubewatch-host" \
"$(stat -c '%g' /var/run/docker.sock)" >> .env
Docker Compose automatically reads .env and substitutes ${KUBEWATCH_API_KEY}, ${KUBEWATCH_SERVER_URL}, and ${DOCKER_GID} in the compose file. The stat call auto-detects the docker group so the agent can read the socket (see Docker socket permissions).
Start the agent
If your stack is already running, bring just the new service up without restarting everything else:
docker compose up -d kubewatch-agent
Or restart the full stack:
docker compose up -d
Verify the agent connected
docker compose logs kubewatch-agent
Look for:
2026/09/08 15:04:05 registered as agent agent_abc123
2026/09/08 15:04:05 starting initial collection (interval=15s)
A successful push isn't logged, only failures are, so no further output for a while is normal. Check the dashboard's agent selector to confirm data is actually arriving.
Docker socket permissions
The agent runs as a non-root user, but /var/run/docker.sock is owned by root:docker. If the agent logs dial unix /var/run/docker.sock: connect: permission denied, grant the container the host's docker group. Find the group's ID:
stat -c '%g' /var/run/docker.sock
Then set it as DOCKER_GID in your .env (the compose above reads ${DOCKER_GID} into group_add):
# .env
DOCKER_GID=999 # whatever the command above printed
Recreate the container so the group takes effect:
docker compose up -d --force-recreate kubewatch-agent
Running Docker Compose with sudo or adding your host user to the docker group does not help, since those affect the host user rather than the process inside the container. If you can't determine the GID, replace the group_add block with user: "0:0", which runs the agent as root. That's acceptable here because socket access is already privileged.
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
KUBEWATCH_API_KEY | Yes | None | Your KubeWatch API key (from Settings → API Keys) |
KUBEWATCH_SERVER_URL | No | Hosted KubeWatch Cloud endpoint | Your KubeWatch host, set to your domain or http://<ip> for self-hosted |
KUBEWATCH_AGENT_NAME | No | hostname | Display name in dashboard |
KUBEWATCH_INTERVAL | No | 15s | Push interval (Go duration, e.g. 15s, 1m) |