One of the most popular features in Maintenant is auto-discovery: deploy the container, and all your services show up in the dashboard with zero configuration. Here’s how it works.
Runtime detection
On startup, Maintenant runs a detection sequence:
- Checks for the presence of
/var/run/secrets/kubernetes.io/serviceaccount/token - If found, switches to Kubernetes mode with in-cluster config
- Otherwise, attempts to connect to the Docker socket (
/var/run/docker.sock) - If found, switches to Docker mode
- The
MAINTENANT_RUNTIMEenvironment variable can be used to force a specific mode
This detection takes less than 100ms at startup.
Docker mode
In Docker mode, Maintenant uses the official Docker SDK for Go. It connects to the Unix socket mounted in read-only mode and performs several operations:
Initial listing
A call to ContainerList with the status=running filter retrieves all active containers. For each container, Maintenant extracts Docker labels, the Compose project name (via the com.docker.compose.project label), exposed ports, and health check configuration.
Event listening
A dedicated goroutine listens to Docker events in real time via Events. Every start, stop, die, and health_status event is captured and processed immediately. This is what allows the dashboard to update in real time via SSE.
Metrics collection
The Docker ContainerStats API provides CPU, memory, network, and disk I/O metrics per container. Maintenant collects them at regular intervals and stores them in SQLite.
Kubernetes mode
In Kubernetes mode, Maintenant uses the official client-go library with in-cluster configuration (service account). The required RBAC is minimal and read-only:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: maintenant-reader
rules:
- apiGroups: [""]
resources: ["pods", "services", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "daemonsets", "statefulsets"]
verbs: ["get", "list", "watch"]
Maintenant never creates, modifies, or deletes anything in your cluster. Observation only.
Workloads
Unlike Docker mode, which operates at the container level, Kubernetes mode operates at the workload level: Deployments, DaemonSets, StatefulSets. Pods are grouped under their parent workload, providing a more meaningful view of your services’ health.
Storage: SQLite in WAL mode
All collected data is stored in SQLite using WAL mode (Write-Ahead Logging). This allows concurrent reads without blocking writes – essential for a tool that continuously collects metrics while serving a real-time dashboard.
Memory footprint remains minimal (~17 MB at rest) thanks to strict goroutine management and Go’s garbage collector.
Conclusion
Auto-discovery is not magic. It’s the smart use of existing Docker and Kubernetes APIs, combined with a lightweight Go architecture and simple storage choices.
The result: you deploy a container, and your stack is monitored. No configuration needed.