Portainer, plain Docker and everything else
CapScope is one Go binary, a Dockerfile and a compose file. Any platform that can run a Docker image can run it — nothing platform-specific is required. This page covers Portainer, plain docker compose, docker run, Swarm, Podman and a generic checklist for NAS boxes and homelab panels.
Portainer
Add the stack
Stacks → Add stack and paste the contents of deploy/docker-compose.yml.
Set the password
Change AUTH_PASS from change-me to a long random password before you expose the port.
Deploy
Deploy the stack. Portainer's own container shows up in the sidebar — hide it with EXCLUDE=^portainer if it is noisy.
docker ps --filter name=capscope
curl -fsS http://localhost:8080/healthz # ok
Plain Docker Compose
cd deploy
docker compose up -d --build
# then open http://<host>:8080
AUTH_PASS defaults to change-me in the compose file — change it before exposing the port.
Plain docker run
docker run -d --name capscope -p 8080:8080 \
-e AUTH_PASS='a long random password' \
-v capscope-data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart unless-stopped \
ghcr.io/hacrex/capscope:latest
Swarm / docker stack deploy
docker stack deploy -c deploy/docker-compose.yml capscope
Generic checklist
For "my NAS, my homelab panel, my reverse-proxy box" — if it runs Docker images, these six items are the whole deployment:
- Image. Build from the
Dockerfileat the repo root, or run the publishedghcr.io/hacrex/capscope:latest. - Persistent volume on
/data— the SQLite database lives there. - Docker API access — mount
/var/run/docker.sock, or setDOCKER_HOST=tcp://…to a socket proxy. AUTH_PASS(mandatory), optionallyAUTH_USER,LOG_RETENTION,MAX_DB_MB,EXCLUDE.- Reverse proxy on port
8080, HTTPS mandatory — Basic auth travels in clear text on HTTP. Health path:/healthz. - One instance only. Never run two CapScope containers against the same
/datavolume.
services:
capscope:
image: ghcr.io/hacrex/capscope:latest
ports: ["8080:8080"]
environment:
AUTH_USER: admin
AUTH_PASS: "${CAPSCOPE_PASS:?set it}"
MAX_DB_MB: 2048
EXCLUDE: "^captain-|^portainer"
volumes:
- capscope-data:/data
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
volumes:
capscope-data:
Podman
Podman's docker alias is a drop-in CLI for the compose and docker run commands above, so the same commands work unchanged with podman-compose or the podman docker-compose shim. Two things differ:
| Topic | Detail |
|---|---|
| Socket path | The Podman-compatible API socket is /run/podman/podman.sock (system service, rootful) or /run/user/$UID/podman/podman.sock (rootless). Mount it, or skip the mount and set DOCKER_HOST=unix:///run/podman/podman.sock — the Go client honours DOCKER_HOST. |
| Rootless caveats | Under rootless Podman CapScope sees only that user's containers, and stats/events depend on Podman's Docker-compatible API emulation level. If the sidebar fills but live tail or snapshots stay silent, check that podman system service is running — or use the rootful socket. The scratch image itself runs fine (static binary, no daemon deps). |
Not supported
Troubleshooting
| Symptom | Likely cause |
|---|---|
Exits at start: AUTH_PASS is required | Set AUTH_PASS, or ALLOW_NO_AUTH=true for a private test. |
Exits at start: cannot reach Docker | Socket not mounted, wrong DOCKER_HOST, or a proxy that does not expose CONTAINERS=1. |
| App list empty | INCLUDE/EXCLUDE filtering everything out, or no containers on this node. |
| Container shows no logs | Its logging driver does not support reading — check whether docker logs fails for it too. |
| Live view stalls behind a proxy | Response buffering on /api/logs/stream; disable it for that path. |
| Database grows fast | Lower LOG_RETENTION, set MAX_DB_MB, or EXCLUDE chatty containers. |