Files
Europium 63 ea1103f52b Initial public release — Inspector v0.7.0
Docker-watchdog with per-container restart rules, Gotify/Pushover
notifications, and an embedded dashboard + web settings page.

See README.md for an overview and INSTALL.md for the Docker quickstart.
2026-10-26 15:44:55 -07:00

5.6 KiB
Executable File
Raw Permalink Blame History

Inspector

Inspector is a small, opinionated Docker-watchdog. It polls the Docker daemon, applies per-container restart rules, pings Gotify and/or Pushover when things go wrong, and gives you a dashboard that shows what's happening right now and what happened earlier today.

Built for home-lab and small-fleet operators who want "it just works" container recovery without standing up a full observability stack.

What Inspector does

  • Polls each configured container on a fixed interval and classifies it: HEALTHY, UNHEALTHY, STARTING, NOT RUNNING, ERROR, UNREACHABLE, CONTAINER NOT FOUND, NO HEALTH CHECK, UNKNOWN.
  • Restarts a container when it crosses a configured error threshold — with cooldowns, grace periods, and an hourly restart cap so a flapping container doesn't DDoS your host.
  • Opt-in HTTP reachability checks per container (useful for VPN-routed containers whose tunnel drops while Docker still reports "healthy").
  • Opt-in Uptime Kuma integration as a second reachability source.
  • Advanced recovery via Portainer stack redeploy for containers whose network namespace is tied to a VPN sidecar.
  • Sends notifications on transitions, not on every poll — one line when something breaks, one line when it recovers.
  • Optional SQLite event history + a daily/weekly digest.
  • Scheduled maintenance windows (don't act during 2–6 AM).
  • Manual notification mute per container, from the dashboard.
  • Embedded web dashboard + events timeline + web settings page for editing config.yml without SSH.

What Inspector is not

  • Not a metrics system. It doesn't scrape Prometheus or push dashboards; use Grafana / Netdata / your real monitoring stack for that.
  • Not an orchestrator. It only acts on containers you've explicitly listed in config.yml.
  • Not multi-host. One Inspector per Docker socket.

Install

See INSTALL.md. TL;DR:

mkdir -p ~/docker/inspector && cd ~/docker/inspector
curl -L -o compose.yml https://gitea.euronvault.com/euronvault/inspector/raw/branch/main/compose.yml
curl -L -o config.yml   https://gitea.euronvault.com/euronvault/inspector/raw/branch/main/config.example.yml
$EDITOR config.yml
echo "DOCKER_GID=$(getent group docker | cut -d: -f3)" > .env
docker compose up -d

Configuration

Everything lives in config.yml next to the compose file. Start from config.example.yml — every key is commented. Highlights:

  • inspector.interval_seconds — poll cadence.
  • inspector.dry_run — classify + log, never restart.
  • notifications.gotify / notifications.pushover — enable either, both, or neither.
  • containers.<name>.max_error_count / cooldown_seconds / grace_period_seconds / max_restarts_per_hour — the restart knobs.
  • containers.<name>.restart_on — which statuses trigger a restart (leave empty for observe-only).
  • containers.<name>.http_check — opt-in HTTP ping.
  • containers.<name>.recovery_action — restart_container (default) or the advanced Portainer-based options.

Dashboard and settings page

If dashboard.enabled: true, Inspector exposes a small web UI on :8080:

  • / — container cards with current status, error bar, phase (cooldown / grace / failing / observe only / maintenance), and maintenance / mute toggles.
  • /events — per-day timeline of status changes, restarts, recoveries, and failures (requires database.enabled: true).
  • /settings — forms for every top-level config section plus one card per container. Saves preserve comments and key order in config.yml and keep a .bak. Fields that take effect on the next loop iteration (per-container thresholds, dry_run, heartbeat, interval_seconds) hot-apply; fields bound at startup are labeled requires restart.

Note on .bak inside Docker: when config.yml is bind-mounted as a single file (the compose default), the .bak lives in the container's overlay fs — the live file still updates cleanly, but the backup is lost when the container is removed. To keep the .bak on the host, bind-mount the directory instead of the single file.

Notifications

Both channels are independent. If both are enabled, every alert goes to both. Inspector sends on transitions:

🚨 first failure threshold crossed
🔁 container restart triggered
✅ restart / start completed
✅ container recovered
🛑 restart failed / hourly limit exceeded
❓ configured container not found

Gotify messages are Markdown; Pushover doesn't render Markdown so the **bold** passthrough is cosmetic — bodies are identical.

Pushover priorities map from Inspector's Gotify-style scale (default 5) to Pushover's -2..2 range: <=2 → -1, 3..4 → 0, 5..6 → 1, >=7 → 2. Priority 2 (emergency) ships default retry / expire and your Pushover client prompts for acknowledgement.

Docker socket security

Inspector talks to /var/run/docker.sock. That socket is effectively root on your host: anything that can write to it can start, stop, inspect, and (through bind mounts) read any file as root. Inspector mounts it read-write because it needs to restart containers.

Follow the usual home-lab precautions:

  • Don't publish the dashboard port on an untrusted network. Use a reverse proxy with auth, a tailnet, or SSH tunneling.
  • Set a strong dashboard.password.
  • Store Portainer / Gotify / Pushover tokens in the config file on a host-only path with permissions 600.

Versioning

Semantic versioning (MAJOR.MINOR.PATCH). Image tags are published for every release; latest tracks the newest tag. Pin a specific version in production — see INSTALL.md.

License

MIT.