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.

Use an API key from Settings → API Keys (a `kw...` value), not a `kwl_ent_...` license key, which lives under Settings → License instead. Also, don't combine `env_file` with an `environment:` entry for the same variable: `environment` takes precedence, so an empty value there will blank out whatever `env_file` set.
Keep `container_name: kubewatch-agent` even though you're merging this into an existing stack. Docker Compose otherwise derives a project-specific name (e.g. `myproject-kubewatch-agent-1`), which breaks the one-click "Update" button on the Connected Agents page: it looks the container up by this exact fixed name. If you already deployed without it and see a stuck "retry update" status, add the line and run `docker compose up -d --force-recreate kubewatch-agent` once to pick it up.

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).

Never commit your `.env` file to version control. Add `.env` to your `.gitignore`.

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.

A ready-made `docker-compose.agent.yml` with all of this pre-wired is published alongside the installer at `https://raw.githubusercontent.com/lloyd-theophilus/kubewatch-releases/main/docker-compose.agent.yml`.

Environment variables

VariableRequiredDefaultDescription
KUBEWATCH_API_KEYYesNoneYour KubeWatch API key (from Settings → API Keys)
KUBEWATCH_SERVER_URLNoHosted KubeWatch Cloud endpointYour KubeWatch host, set to your domain or http://<ip> for self-hosted
KUBEWATCH_AGENT_NAMENohostnameDisplay name in dashboard
KUBEWATCH_INTERVALNo15sPush interval (Go duration, e.g. 15s, 1m)