Deploying CapScope on Dokku
Dokku builds the repository's Dockerfile on git push — no buildpack needed. The CHECKS file at the repo root makes Dokku wait for /healthz before it routes any traffic.
1. Create the app
dokku apps:create capscope
# persistent storage — the SQLite database survives redeploys
dokku storage:ensure-directory capscope --chown-on-add
dokku storage:mount capscope /var/lib/dokku/data/storage/capscope:/data
# Docker socket access
dokku storage:mount capscope /var/run/docker.sock:/var/run/docker.sock
The storage:mount commands take effect on the next deploy, so mount them before your first push.
docker.sock is root equivalent. Skip the second mount and use the socket proxy in step 5 if you want CapScope to have read-only access.2. Configure it
dokku config:set capscope AUTH_USER=admin AUTH_PASS='a long random password'
dokku config:set capscope MAX_DB_MB=2048 # optional size cap
dokku config:set capscope EXCLUDE='^nginx|traefik' # hide Dokku's own proxies
Worth excluding: the per-app nginx sidecars Dokku adds and the traefik/caddy ingress containers — they are noisy. Excluded containers are still followed for access logs only, so your Access dashboard keeps working.
| Key | Value |
|---|---|
AUTH_USER / AUTH_PASS | Mandatory password — the server refuses to start without it. |
MAX_DB_MB | Hard cap on database size; oldest data dropped first. |
EXCLUDE | Regex over container and app names. |
LOG_RETENTION | Default 7d — raise it if disk allows. |
3. Deploy
git remote add dokku dokku@<your-dokku-host>:capscope
git push dokku main
The first build downloads Go modules, so the Dokku host needs outbound internet during the build.
HTTPS
dokku domains:set capscope capscope.example.com
dokku letsencrypt:set --global email you@example.com
dokku letsencrypt capscope
dokku letsencrypt capscope before the certificate expires.Scaling
Keep it at 1 process. The Dockerfile build already defaults to a single web process; do not run dokku ps:scale capscope web=2 or higher — instances would write the same SQLite file.
4. Socket proxy (recommended)
Run the proxy
Start tecnativa/docker-socket-proxy with CONTAINERS=1, EVENTS=1, PING=1, POST=0, no public port, on the same Docker network as CapScope.
Remove the socket mount
Instead of mounting the socket, point CapScope at the proxy:
dokku config:set capscope DOCKER_HOST=tcp://<proxy-container-name>:2375
Re-deploy
git push dokku main again. CapScope only issues GET requests, so the proxy can stay fully read-only.
5. Notes
| Topic | Detail |
|---|---|
| Ports | The Dockerfile exposes 8080 and Dokku maps the first exposed port automatically, so no ports:set is needed. If you skip the web proxy: dokku ports:set capscope http:80:8080. |
| Live tail (SSE) | CapScope sends X-Accel-Buffering: no, which Dokku's default Nginx proxy respects. Behind another reverse proxy, disable response buffering for /api/logs/stream. |
| Health check | /healthz — auth-free by design; the CHECKS file already uses it. |
| Container user | Runs as root on purpose — docker.sock needs it. |
| Crash catch-up | Deaths that happened while CapScope was down are replayed from the persisted event cursor on startup (up to 24 h back). |
6. Verify
Open the app
Visit https://capscope.example.com and log in. The header chip should show a container count above zero.
Check the sidebar
Your apps appear on the left; containers matched by EXCLUDE stay out but still feed the Access dashboard.
Trigger a test crash
Run a container that exits with code 1 and confirm a snapshot appears under Crashes with an exit code and log tail.
/data lives outside the container, redeploys, rebuilds and rollbacks never touch your log history, snapshots or alert rules.