# The agent in Docker

Run the agent in Docker or Podman.

Get a host token from **Hosts → Add a server** first.

## Start with Compose

1. Save this file:

```yaml title="agent.compose.yml"
services:
  kogut-agent:
    image: ghcr.io/piotrkowski/kogut-agent:0.1
    command: ["agent"]
    restart: unless-stopped
    network_mode: host
    pid: host
    group_add:
      - "${DOCKER_GID:?set DOCKER_GID to the group id of /var/run/docker.sock}"
    environment:
      - KOGUT_SERVER=https://kogut.acme.com
      - KOGUT_TOKEN=${KOGUT_TOKEN}
      - KOGUT_HOST_ROOT=/host
      - KOGUT_STATE_DIR=/data
    volumes:
      - agent-state:/data
      - /:/host:ro,rslave
      - /var/run/docker.sock:/var/run/docker.sock:ro

volumes:
  agent-state:
```

2. Set your server URL above and put the token in a `.env` file beside the Compose file:

```sh title=".env"
KOGUT_TOKEN=<token from the panel>
```

3. Start the agent with the socket's group id:

```sh
DOCKER_GID=$(stat -c %g /var/run/docker.sock) docker compose -f agent.compose.yml up -d
```

The same file is in
[deploy/docker/agent.compose.yml](https://github.com/piotrkowski/kogut/blob/main/deploy/docker/agent.compose.yml).

- Host networking gives network metrics, listening-port discovery, and Caddy access.
- `pid: host` gives the host's processes and mount table.
- The host-root mount gives metrics, filesystems, temperatures, and nginx configuration;
  `rslave` includes later host mounts. Only the state volume is writable.

`ghcr.io/piotrkowski/kogut-agent` holds the
[agent-only build](https://docs.kogut.dev/reference/cli/#the-agent-only-build). The server image
`ghcr.io/piotrkowski/kogut` runs the same agent with `command: ["agent"]`.

The image runs as uid `65532`, so socket access needs `group_add`. It has no `systemctl`
or `journalctl`; for systemd states and logs, [install on the host](https://docs.kogut.dev/agent/installing/). When
the agent cannot use the socket, see
[When the agent cannot read a source](https://docs.kogut.dev/agent/permissions/#when-the-agent-cannot-read-a-source).

## Run the agent inside the server container

On the host that runs kogut, `KOGUT_LOCAL_AGENT=1` runs the agent inside the server,
with no token or agent container. Give the server container what the agent service above
has: `network_mode: host`, `pid: host`, `KOGUT_HOST_ROOT=/host` with the
`/:/host:ro,rslave` mount, and the Docker socket with `group_add` and `DOCKER_GID`. Host
networking replaces the `ports:` mapping: kogut listens on port 8484 of the host.
[Monitor the same host](https://docs.kogut.dev/installation/docker-compose/#monitor-the-same-host) has the
Compose file.

## Container alerts

The agent reports each container's state, health, restart count, exit code, image, and
OOM kills. A container of a service raises an alert when it restarts in a loop, exits
with an error, or stays unhealthy; see [Containers](https://docs.kogut.dev/alerts/how-alerts-work/#containers).
An OOM kill becomes the [likely cause](https://docs.kogut.dev/incidents/correlation/) of the incident, and a
new image is recorded as a [deploy](https://docs.kogut.dev/deploys/containers/).

Exit codes, OOM kills, and image ids need an updated agent. Older agents report restarts
and health only.

## Use a socket proxy instead of the socket

The Docker socket grants control of the host even when mounted read-only
([Permissions](https://docs.kogut.dev/agent/permissions/)). A socket proxy limits the API the agent can use.

1. Start the proxy on `127.0.0.1:2375` with container and image reads enabled
   (`CONTAINERS=1`, `IMAGES=1`) and writes disabled (`POST=0`). Without `IMAGES=1`, the
   [rollback hint](https://docs.kogut.dev/deploys/containers/#rollback-hint) shows image ids, not digests.
2. Remove `group_add` and the Docker socket mount from the agent's Compose service.
3. Add `DOCKER_HOST=tcp://127.0.0.1:2375` to its environment and recreate the agent.

Do not expose the proxy beyond loopback.

## Use Podman

For rootful Podman, mount `/run/podman/podman.sock` at `/var/run/docker.sock` and use its
group id. For rootless Podman, run the agent as the socket's owner and mount
`$XDG_RUNTIME_DIR/podman/podman.sock` instead.

Rootless Podman reports container state, health, restarts, and exit codes, so container
alerts work, but no CPU or memory: the agent reads those only from the Docker and rootful
Podman cgroup v2 layouts. Socket selection and token files are in
[agent environment variables](https://docs.kogut.dev/reference/environment-variables/#agent).
