Docker Awakening Gateway — Roadmap
✅ Completed
Core
- On-demand container startup — containers sleep until a request arrives, then are started via Docker API
- Transparent reverse proxy — once running, requests are proxied with zero loading page overhead
- Concurrency-safe start — per-container mutex prevents duplicate start attempts on concurrent requests
- WebSocket support — upgrade requests are tunnelled via raw TCP hijack to the backend
- Host-header routing — O(1) lookup maps
Hostheader → container config; supports N containers on one gateway - Query-param fallback —
?container=NAMEfor testing without DNS
Configuration & Operations
- YAML config file (
config.yaml) — per-container settings, mounted via volume CONFIG_PATHenv override — point to any path for the config file- Config validation at startup — gateway fails-fast if
config.yamlis missing required fields or contains duplicate definitions - Config hot-reload —
docker kill -s HUP docker-gatewayreloadsconfig.yamlat runtime without dropping connections - Label-based auto-discovery — gateway reads Docker labels (
dag.host,dag.target_port, etc.) to automatically discover containers - Per-container
start_timeout— max time to wait for docker start + TCP probe - Per-container
idle_timeout— auto-stop containers idle longer than threshold (0 = disabled) - Per-container
target_port,network,redirect_path - Global
log_lines— number of container log lines shown in the loading UI - Configurable discovery interval —
gateway.discovery_intervalorDISCOVERY_INTERVALenv var
Reliability
- TCP readiness probe — after Docker reports “running”, dial
ip:portuntil the app responds - HTTP health probe — optionally call a container’s
/healthendpoint to confirm readiness - Early crash detection — if container enters
exited/deadduring start, fail immediately - Start state tracking —
starting/running/failedstates with error message, exported via/_health - Idle watcher goroutine — background loop (every 60s) auto-stops containers exceeding
idle_timeout - Multi-network support — resolves container IP from a named Docker network; falls back to first available
- Graceful shutdown —
SIGTERM/SIGINTtriggershttp.Server.Shutdown()with grace period
Security
- Read-only Docker socket — gateway only needs
ContainerInspect,ContainerStart,ContainerStop,ContainerLogs - Distroless final image (
gcr.io/distroless/static) — no shell, no package manager, ~22 MB - Rate limiter on internal endpoints — 1 req/s per IP on
/_healthand/_logs - XSS-safe log rendering — log lines injected via
textContent, notinnerHTML - Vendored dependencies — no network access needed during Docker build
- Admin endpoint authentication — optional basic-auth or bearer token to protect
/_status/*and/_metrics - CORS / CSRF protection on
/_status/wake— prevent cross-origin container start abuse - Rate limiter memory cleanup — periodic eviction of stale IPs to prevent unbounded memory growth
- Trusted proxy configuration — only trust
X-Forwarded-Forfrom known upstream proxies
Proxy Headers
X-Forwarded-For— appends client IP to the forwarding chainX-Real-IP— original client IP (not overwritten if already set upstream)X-Forwarded-Proto— upstream value preserved; defaults tohttpX-Forwarded-Host— originalHostheader value
Frontend (loading page)
- Animated loading page — dark-themed, breathing container icon, barber-pole progress bar
- Live log box — polls
/_logsevery 3s, renders last N lines with auto-scroll - Inline error state — on
status=failed, swaps progress bar for error box in-place; shows retry button - Auto-redirect on ready — polls
/_healthevery 2s; navigates toredirect_pathwhen running
Admin & Observability
/_statusdashboard — HTML admin page with live status, heartbeat bars, uptime, last request, dark/light mode/_status/apiJSON endpoint — snapshot of all containers, polled every 5s/_status/wakeaction — POST endpoint to trigger container start from dashboard- Prometheus
/metricsendpoint — per-container counters for requests, starts, durations, idle stops
Groups & Dependencies
- Container grouping / round-robin routing — start a group of containers, load-balance across replicas
- Dependency-ordered startup —
depends_ontriggers topological sort before proxying
Quality
- Structured logging — Go 1.21+
log/slogJSON-structured output - Discovery change detection — only reload when merged config actually differs
- Unit tests — table-driven tests for config, discovery, rate limiter, proxy routing, security
📅 Medium-term
- Customisable loading page — per-container colour/logo/message overrides
- Weighted load balancing — support
strategy: weightedwith per-container relative weights
🔭 Long-term
- Multi-instance / distributed state — share
startStatesandlastSeenvia Redis or etcd - Built-in TLS termination — ACME/Let’s Encrypt via
golang.org/x/crypto/acme/autocert
Known Limitations (by design)
- Single host only — communicates with the local Docker socket; remote Docker hosts not supported
- HTTP only — TLS expected to be handled by an upstream proxy (Nginx, Caddy, Traefik)
- In-memory state — start states and activity timestamps reset on gateway restart