CapScope documentation
CapScope is a single Go binary that watches your Docker daemon, stores logs and CPU/memory samples in SQLite, and keeps a crash snapshot every time a container exits non-zero or is OOM killed. This section covers concepts, configuration, alerting, internals and the HTTP API.
Configuration
Every environment variable, its default and what it controls — listen address, retention, budgets, redaction, filtering.
Alert rules
Dead-man, restart-loop, metric and log-pattern rules in a hot-reloaded JSON file, plus webhook, Telegram, Slack and Discord.
Architecture
Components, data flow, crash-snapshot sequence, storage schema, concurrency model, failure modes and trade-offs.
API reference
Logs, SSE stream, metrics, snapshots, access logs, SQL, deploys and alerts — parameters, shapes and rules.
What it does
| Area | What you get |
|---|---|
| Live logs | Per-app sidebar, virtual-scrolled live tail over SSE, pause/follow, load older, split view for up to 4 replicas side by side, JSON pretty-print on click. |
| Search history | FTS5 full-text search, regex mode, or raw SQL via /api/sql; filter by level, stream and replica. |
| History after redeploy | Logs and samples persist in SQLite with age and size retention — searchable long after the container is gone. |
| Crash snapshots | Exit code, OOM flag, restart count, uptime, last N log lines, last N metric samples, plain-language summary, Markdown export. |
| Restart loops | Deaths counted in a sliding window; looping containers flagged with ↻. |
| Access logs | GoAccess-style panels: status codes, top paths, IPs (anonymized), referrers, timeline, CSV export. |
| Deploy markers | Recorded from CI or the UI; drawn on charts, inline in the timeline, attached to crash details. |
| Alerts | Four rule kinds, four channels, hot-reloaded rules file, test button in the UI. |
| Security | Secret redaction before storage, Basic auth required by default. |
Core concepts
Apps and replicas
CapScope groups containers into apps. CapRover's Swarm service label com.docker.swarm.service.name wins first, then Docker Compose labels, then the container name. Replica slots (srv-captain--shop.1.x) are split off so replicas of one app appear together in the sidebar and can be compared side by side.
Where data lives
One SQLite file, normally /data/capscope.db on a persistent volume. Tables: logs, metrics, containers, snapshots, access, alerts, deploys and state. WAL mode plus a read-only connection pool means dashboard queries never block ingestion.
MAX_DB_MB cap (oldest logs first), then incremental_vacuum.Search modes
- Text — case-insensitive FTS5 token/prefix index, falling back to
LIKEso mid-word searches still work. - Regex — case-insensitive regular expression; invalid patterns return
400. - SQL — one read-only
SELECTover the stored tables with a 5-second deadline and a 5000-row cap.
Lifecycle of a crash
Event arrives
Docker emits die / oom / kill. The collector detaches the container's tracker so a fast restart cannot race it.
Evidence is flushed
The log follower is given up to 2 seconds to drain. Snapshot evidence comes from in-memory ring buffers, not the database, because writes are batched and can lag by up to 250 ms.
Classification
OOM wins, exit 0 is clean_exit, an earlier stop/kill signal makes it killed, everything else is crash.
Snapshot + summary
Metadata, trimmed inspect, last 200 lines and 60 samples are stored with a rule-based summary. Deaths are deduplicated by (container_id, die_ts).
Handoff
Export as Markdown — exit code, restart window, last deploy, trend and log tail — straight into an incident channel.
Requirements
| Need | Detail |
|---|---|
docker.sock | Read access to the Docker Engine API — the socket itself, or a read-only socket proxy via DOCKER_HOST=tcp://…. |
/data volume | SQLite lives here. Without it, history and snapshots die on redeploy. |
AUTH_PASS | Mandatory. The server refuses to start without it unless ALLOW_NO_AUTH=true. |
| Port | 8080 in the container. Terminate TLS in front of it — Basic auth over plain HTTP travels in clear text. |
| Log drivers | json-file, local and journald are supported through the Docker logs API. |
| Replicas | Exactly one. Two CapScope instances against the same database would fight over the single writer. |
Install it
docker run -d --name capscope \
-p 8080:8080 \
-e AUTH_PASS='change-me' \
-v capscope-data:/data \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart unless-stopped \
ghcr.io/hacrex/capscope:latest
Or build from source:
git clone https://github.com/hacrex/CapScope.git
cd CapScope
make run # http://127.0.0.1:8080 (local testing, no auth)
make demo # UI with fake data
make test # full test suite
captain-.Next: platform-specific deployment steps in the deployment guides, or dive into the configuration reference.