L’une des fonctionnalités les plus appréciées de Maintenant est l’auto-découverte : déployez le conteneur, et tous vos services apparaissent dans le dashboard sans configuration. Voici comment ça fonctionne.
Détection du runtime
Au démarrage, Maintenant exécute une séquence de détection :
- Si la variable
MAINTENANT_RUNTIMEest définie, elle impose le mode - Sinon, si
KUBERNETES_SERVICE_HOSTest définie → mode Kubernetes avec in-cluster config - Sinon, essaie un kubeconfig (
KUBECONFIGou~/.kube/config) et l’utilise si le cluster répond - Sinon, se connecte au socket Docker (
/var/run/docker.sock) → mode Docker
Mode Docker
En mode Docker, Maintenant utilise le SDK Docker officiel pour Go. Il se connecte au socket Unix monté en lecture seule et effectue plusieurs opérations :
Listing initial
Un appel à ContainerList récupère tous les conteneurs, y compris ceux qui sont arrêtés. Pour chaque conteneur, Maintenant extrait les labels Docker, le projet Compose (via le label com.docker.compose.project), les ports exposés, et la configuration de health check.

Écoute des événements
Un goroutine dédié écoute les événements Docker en temps réel via Events. Chaque événement start, stop, die, health_status est capté et traité immédiatement. C’est ce qui permet au dashboard de se mettre à jour en temps réel via SSE.
Collecte de métriques
L’API Docker ContainerStats fournit les métriques CPU, mémoire, réseau et I/O disque par conteneur. Maintenant les collecte à intervalle régulier et les stocke dans SQLite.

Mode Kubernetes
En mode Kubernetes, Maintenant utilise le client-go officiel avec la configuration in-cluster (service account). Le RBAC nécessaire est minimal et en lecture seule :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: maintenant
rules:
- apiGroups: [""]
resources: ["namespaces", "nodes", "pods", "events", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets", "daemonsets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list"]
Maintenant ne crée, ne modifie et ne supprime jamais rien dans votre cluster. Observation uniquement.
Workloads
Contrairement au mode Docker qui raisonne en conteneurs, le mode Kubernetes raisonne en workloads : Deployments, DaemonSets, StatefulSets. Les pods sont regroupés sous leur workload parent, offrant une vue plus pertinente de l’état de vos services.
Le stockage : SQLite en WAL mode
Toutes les données collectées sont stockées dans SQLite en mode WAL (Write-Ahead Logging). Ce choix permet des lectures concurrentes sans bloquer les écritures, essentiel pour un outil qui collecte des métriques en continu tout en servant un dashboard temps réel.
La mémoire reste modeste (environ 100 Mo de RAM après plusieurs jours sur un hôte chargé), le garbage collector de Go se chargeant de l’entretien.
Conclusion
L’auto-découverte n’est pas de la magie. C’est l’utilisation intelligente des APIs existantes de Docker et Kubernetes, combinée à une architecture Go légère et des choix de stockage simples.
Le résultat : vous déployez un conteneur, et votre stack est monitorée. Sans configuration.
Installer Maintenant → · Comparer les éditions →