Skip to content

Toyz/hope

Repository files navigation

hope

A clean, self-hostable manager for a Docker Compose cluster. One Go binary (sov backend) embeds a loom frontend, reads Docker Compose labels to group containers into stacks, and drives full stack lifecycle — all over the Docker API, so it works against a local socket or a remote daemon with no compose files on disk.

Docs: https://mininote.ink/s/dzW9c7aSbkHOGeD5-jH1qA

Screenshots below use a demo dataset — not a real cluster.

Mission-control overview

Stack control + replica grouping Streaming logs
Stack detail Logs

Features

  • Mission-control overview — every stack at a glance; trouble lights up, the rest stays quiet. A fleet ribbon + synthesized health verdict.
  • Stack control — start / stop / restart / pull / redeploy per stack, and per container, driven entirely through the Docker API (no docker compose shell-out, no mounted compose files). Redeploy pulls images and recreates containers in place, preserving config, networks, and compose labels.
  • Replica grouping — services with multiple containers collapse into one row with bulk actions; expand for per-replica control.
  • Live logs & stats — per container, per service (all replicas multiplexed and source-tagged), or the whole stack. Streamed as NDJSON; auto-scroll + wrap toggle.
  • Update detection — a background crawler compares each container's image against its registry (a manifest lookup — never pulls layers) and flags what's out of date: a dashboard "updates" section, per-row chips on the stack page, and an "update available" button on the container page that redeploys to the latest.
  • Host insight — the dashboard shows the Docker daemon's identity and capacity (version, OS/arch, CPUs, memory, container/image counts) plus cached disk usage (images / volumes / build cache) with an on-demand df refresh.
  • Images view — every local image at a glance (repo:tag, id, size, age) with in-use / unused / dangling tags, searchable, sorted largest-first.
  • Private registry pulls — reads a Docker config.json so pull/redeploy authenticate to private registries (e.g. ghcr).
  • Guarded destructive actions — stop / kill / redeploy require confirmation.
  • Single login — username/password from config; stateless HMAC bearer tokens.
  • Optional socket proxy — expose the Docker API to a trusted LAN behind a method/path allowlist.
  • Container plugins — any container can ship its own hope panel (tables, detail pages, images, charts, live streams, actions) by exposing a small JSON-RPC endpoint and a few labels. hope discovers it across the fleet, and — once enabled — renders it and proxies every call; the browser never touches the plugin. Extend hope in your own container, language, and release cadence — no hope recompile. See the plugin protocol, the Go SDK on pkg.go.dev, and the example plugins (hello-world, hope-postgres, kitchen-sink).

Quick start

cp config.example.toml config.toml   # then edit: username, password, token_secret
cp docker-compose.example.yml docker-compose.yml
docker compose up -d --build

Open http://<host>:8080 and sign in. hope reaches the daemon through the mounted /var/run/docker.sock.

Configuration

See config.example.toml. Every key can be overridden with a HOPE_* env var (e.g. HOPE_AUTH_PASSWORD). Key sections:

  • [auth]username, password (plaintext or a $2… bcrypt hash), and a long random token_secret.
  • [docker] hostunix:///var/run/docker.sock or a remote tcp://host:2375. config optionally points at a Docker config.json for registry credentials (defaults to ~/.docker/config.json). hope reads only inline auth entries — docker login writes those on Linux. Credential helpers / credsStore keep secrets outside the file and can't run in hope's minimal container. Podman works too — it serves the same API: run podman system service and point host at its socket (unix:///run/podman/podman.sock, or unix://$XDG_RUNTIME_DIR/podman/podman.sock rootless). hope groups stacks by the Docker or podman compose labels (io.podman.compose.*), so podman compose / podman-compose projects show up grouped.
  • [auth] api_keys — optional static keys for headless RPC (pass one as the bearer token). Enabling them also turns on the in-app API explorer at /api and sov's schema at /rpc/_introspect. Off by default. See the in-app API page for the calling convention.
  • [[registry]] — explicit registry credentials (server / username / password), the reliable way to authenticate pulls without mounting a config.json or running a helper. Use a Docker Hub account + access token so pulls aren't anonymous and rate-limited. Repeat per registry. An authenticated pull that the registry rejects (rate limit, bad creds) now fails the redeploy loudly instead of silently keeping the old image.
  • [updates] — the image-freshness crawler. enabled (default true), interval (default 6h; mind Docker Hub anonymous rate limits), and an optional cache_path that persists the freshness cache to disk so it survives restarts — mount that path to keep it across container recreates, e.g. cache_path = "/data/updates.json" with a /data volume.
  • [socketproxy] — opt-in LAN proxy; read-only by default.
  • [log]color / json.

Security

  • Mounting the Docker socket grants root-equivalent control of the host to the hope container. Run it only on a trusted network (LAN / overlay like ZeroTier), behind its login — not on a public interface.
  • The socket proxy is the same exposure to whoever reaches its port. It defaults to read-only (GET/HEAD); only allowlist writes deliberately, and never route it through a public tunnel.

Development

Backend (live reload with air):

air            # builds ./cmd/hope, restarts on change (uses ./config.toml)

Frontend (Vite dev server, proxies /rpc to the backend on :8080):

cd frontend && npm install && npm run dev

Build

cd frontend && npm run build      # outputs frontend/dist (embedded by the binary)
go build -o hope ./cmd/hope       # single self-contained binary

Or build the image: docker build -t hope .. If github.com/Toyz/sov is private, pass build credentials (see the Dockerfile header).

Architecture

  • Backend (cmd/hope, internal/*): sov gateway. internal/docker wraps the Docker SDK and groups containers by compose label; internal/stacks, internal/containers, internal/system are RPC routers; internal/auth is the sov AuthService; internal/plugins/logstream streams NDJSON logs/stats; internal/plugins/logger is the unified request logger; internal/socketproxy is the optional LAN proxy. The built SPA is embedded via go:embed.
  • Frontend (frontend/): loom + loom-rpc. A custom RpcTransport adds the bearer token and implements stream() over the NDJSON routes. Pages: login, dashboard (mission control), stack detail, container detail.

License

MIT — see LICENSE.

About

Because I had hope for a docker manager

Topics

Resources

License

Stars

6 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages