
Vous faites tourner une pile Docker et vous voulez savoir en un coup d'oeil ce qui est en vie, sans installer une usine à gaz ? Ce guide déploie Maintenant, un moniteur Docker et Kubernetes en un seul binaire Go, puis le branche sur votre hôte sans jamais monter le socket Docker dans le conteneur. Vous obtiendrez la découverte automatique des conteneurs, une sonde HTTP déclarée en label, une page de statut, et surtout une installation durcie qui ne transforme pas votre supervision en porte d'entrée. Public visé : administrateurs et DevOps à l'aise avec Docker Compose.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déployer Maintenant avec Docker Compose derrière un socket proxy
- Vérifier que la découverte des conteneurs fonctionne
- Surveiller un service HTTP avec une sonde déclarée en label
- Suivre une tâche planifiée avec un heartbeat
- Publier une page de statut
- Sécuriser l'accès, sachant que l'outil n'a pas d'authentification interne
Qu'est-ce que Maintenant ?
Section intitulée « Qu'est-ce que Maintenant ? »Maintenant est un moniteur self-hosted écrit par Benjamin Touchard (kOlapsis). Il tient dans un binaire Go unique avec son interface Vue embarquée, stocke tout dans SQLite et consomme une vingtaine de méga-octets de mémoire. Son principe directeur le distingue des moniteurs classiques : au lieu de déclarer chaque cible à la main, il découvre automatiquement les conteneurs Docker ou les charges Kubernetes, et lit ses sondes dans les labels. La supervision suit donc le cycle de vie des services au lieu de vivre à côté.
Il couvre les besoins courants d'un petit parc : disponibilité HTTP et TCP, heartbeats pour les tâches planifiées, expiration des certificats TLS, métriques CPU et mémoire, et une page de statut publique. C'est un projet open-core sous licence AGPL-3.0 : l'édition Community est complète pour un usage mono-hôte, l'édition Pro ajoute le multi-hôte et l'escalade d'alertes.
Maintenant ou Uptime Kuma ?
Section intitulée « Maintenant ou Uptime Kuma ? »Les deux outils publient une page de statut et surveillent des services, mais ils ne visent pas le même usage. Le tableau suivant aide à choisir sans se tromper.
| Critère | Maintenant | Uptime Kuma |
|---|---|---|
| Déclaration des sondes | Labels Docker, automatique | À la main dans l'interface |
| Cible privilégiée | Docker, Kubernetes | Tout service (HTTP, TCP, DNS, VPS) |
| Découverte des conteneurs | Oui, native | Non |
| Canaux d'alerte | Webhook natif, reste en Pro | Plus de 90, tous gratuits |
| Maturité | Jeune, un mainteneur | Établi, large communauté |
En pratique : si votre parc est surtout conteneurisé, Maintenant réclame beaucoup moins de configuration. Pour un mélange de conteneurs, de VPS et d'API externes, Uptime Kuma reste plus polyvalent. Les deux peuvent cohabiter.
Prérequis
Section intitulée « Prérequis »- Un hôte Linux avec Docker Engine et le plugin Compose, voir installer Docker
- Un accès
sudosur cet hôte - De quoi joindre l'interface en local (port sur la loopback), ou un reverse proxy Traefik devant si vous l'exposez
Déployer Maintenant sans exposer le socket Docker
Section intitulée « Déployer Maintenant sans exposer le socket Docker »Pour découvrir les conteneurs, Maintenant a besoin de lire l'API Docker.
L'installation naïve consiste à lui monter /var/run/docker.sock. C'est une
mauvaise idée, même en lecture seule : parler au socket équivaut à être root
sur l'hôte, et le drapeau :ro ne protège que le fichier, pas l'API. Nous
plaçons donc un docker-socket-proxy entre les deux, qui rejette toute
écriture avec un code 403. Maintenant respecte la variable DOCKER_HOST,
ce montage n'est donc pas nécessaire.
-
Créer le fichier
compose.yamlavec le proxy en amont et Maintenant qui pointe dessus. Les images sont épinglées par empreinte.services:# Composant root-equivalent : il porte le vrai socket, reste sur un# réseau interne et ne publie aucun port sur l'hôte.socketproxy:image: tecnativa/docker-socket-proxy@sha256:1f3a6f303320723d199d2316a3e82b2e2685d86c275d5e3deeaf182573b47476 # v0.4.2environment:CONTAINERS: 1 # découverte, inspect, stats, logsINFO: 1 # détection du runtimeNETWORKS: 1 # métadonnées réseau# EVENTS, PING et VERSION sont déjà actifs par défaut.# POST reste à 0 : toute écriture renvoie 403.volumes:- /var/run/docker.sock:/var/run/docker.sock:ronetworks: [dockerapi]read_only: truetmpfs: [/run, /tmp] # le proxy écrit sa conf haproxy dans /tmpsecurity_opt:- no-new-privileges:truerestart: unless-stoppedmaintenant:image: ghcr.io/kolapsis/maintenant@sha256:0f524deeef333735f34b59fa29013a3f876d09721ecbccfcbc1a143f29d9a627 # 1.3.5environment:DOCKER_HOST: tcp://socketproxy:2375 # parle au proxy, jamais au vrai socketMAINTENANT_ADDR: "0.0.0.0:8080"MAINTENANT_DB: /data/maintenant.dbMAINTENANT_DISABLE_TELEMETRY: "1"volumes:- /proc:/host/proc:ro- maintenant-data:/dataports:- "127.0.0.1:8899:8080" # loopback uniquement, voir la section Sécuriténetworks: [dockerapi, web]depends_on: [socketproxy]read_only: truesecurity_opt:- no-new-privileges:truetmpfs:- /tmp:noexec,nosuid,size=64mrestart: unless-stoppednetworks:dockerapi:internal: true # le proxy n'est joignable que depuis ce réseauweb: {}volumes:maintenant-data: {} -
Démarrer la pile.
Fenêtre de terminal docker compose up -d -
Attendre que Maintenant se connecte au proxy. Au premier démarrage il peut afficher un mode dégradé le temps que le proxy réponde, puis se reconnecte seul.
Fenêtre de terminal curl -s http://127.0.0.1:8899/api/v1/healthLa sortie doit indiquer le runtime connecté et confirmer la version :
{"runtime":{"connected":true,"name":"docker"},"status":"ok","version":"1.3.5"}
Vérifier que la supervision fonctionne
Section intitulée « Vérifier que la supervision fonctionne »Une installation qui démarre n'est pas une installation qui voit vos conteneurs. La commande suivante confirme que la découverte a bien traversé le proxy.
curl -s http://127.0.0.1:8899/api/v1/containers | \ python3 -c "import sys,json;print(json.load(sys.stdin)['total'], 'conteneurs découverts')"Le nombre renvoyé doit correspondre aux conteneurs actifs de l'hôte. Ouvrez ensuite http://127.0.0.1:8899 dans un navigateur : le tableau de bord liste les conteneurs, leur état, et remonte déjà des constats de sécurité (ports exposés, conteneurs privilégiés) sans aucune configuration.
Surveiller un service avec une sonde HTTP
Section intitulée « Surveiller un service avec une sonde HTTP »Le trait qui distingue Maintenant : une sonde n'est pas un formulaire à remplir,
c'est un label posé sur le conteneur à surveiller. Elle vit et meurt avec le
service. Ajoutez ces labels sur un conteneur applicatif, par exemple un serveur
web nommé demo-web :
services: demo-web: image: nginx@sha256:5616878291a2eed594aee8db4dade5878cf7edcb475e59193904b198d9b830de networks: [web] labels: maintenant.endpoint.http: "http://demo-web:80/" maintenant.endpoint.interval: "10s" maintenant.endpoint.failure-threshold: "2"Après un docker compose up -d, la sonde apparaît sans autre geste :
curl -s http://127.0.0.1:8899/api/v1/endpoints | \ python3 -c "import sys,jsonfor e in json.load(sys.stdin)['endpoints']: print(e['container_name'], e['status'], e['last_http_status'])"Une sonde saine affiche up et 200. Pointez volontairement une URL
inexistante (/health sur un nginx nu) pour observer la bascule en down après
le nombre d'échecs configuré : c'est la meilleure façon de vérifier que
l'alerte se déclenchera le jour venu.
Surveiller une tâche planifiée
Section intitulée « Surveiller une tâche planifiée »Un heartbeat surveille l'inverse d'un service web : non pas « répond-il ? » mais « s'est-il exécuté à l'heure ? ». Idéal pour une sauvegarde nocturne ou un cron. On crée le moniteur, on récupère une URL, et la tâche la contacte à la fin de son travail.
curl -s -X POST http://127.0.0.1:8899/api/v1/heartbeats \ -H 'Content-Type: application/json' \ -d '{"name":"sauvegarde-nuit","interval_seconds":3600,"grace_seconds":300}'La réponse contient un identifiant. La tâche planifiée ajoute alors un simple appel en fin d'exécution :
# à la fin du script de sauvegardecurl -fsS -o /dev/null "http://127.0.0.1:8899/ping/<identifiant>"Tant que le ping arrive dans la fenêtre (intervalle plus délai de
grâce), la sonde reste au vert. Passé ce délai sans signe de vie, Maintenant
lève une alerte deadline_missed. L'URL de ping vaut mot de passe : traitez
l'identifiant comme un secret et ne le commitez jamais.
Publier une page de statut
Section intitulée « Publier une page de statut »Maintenant expose une page de statut publique à l'adresse /status,
alimentée par les sondes déjà en place. Elle est prévue pour être accessible
sans authentification, contrairement au tableau de bord. Vérifiez qu'elle
répond :
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8899/status/apiUn code 200 confirme que l'API publique de la page fonctionne. La composition
des composants affichés et le nom de l'organisation se règlent dans le tableau
de bord, section statut.
Sécuriser l'accès
Section intitulée « Sécuriser l'accès »C'est le point le plus important de ce guide, et il mérite d'être dit sans
détour. Maintenant n'a pas d'authentification interne, par conception. Comme
Prometheus ou Dozzle, il délègue cette responsabilité à un reverse proxy. La
conséquence est directe : quiconque atteint le port de l'interface a un accès
complet à l'API d'administration, peut lire les journaux des conteneurs
(donc d'éventuels secrets qui s'y trouvent) et créer des webhooks. C'est
pourquoi le compose.yaml de ce guide publie le port sur 127.0.0.1
uniquement.
Trois mesures forment le socle d'un déploiement sain :
- Ne jamais publier le port sur toutes les interfaces. Gardez
127.0.0.1:8899:8080en local, ou une IP de LAN précise, jamais8899:8080seul. Maintenant lui-même signale d'ailleurs un port exposé comme un risque critique, y compris sur son propre conteneur. - Mettre un reverse proxy authentifié devant pour tout accès distant :
Traefik couplé à Authelia, par exemple. Les
routes
/api/v1/et/exigent l'authentification ; seules/ping,/statuset le manifeste restent publiques. - Filtrer l'API Docker par un socket proxy, comme fait plus haut. Le détail
de ce mécanisme et la démonstration de pourquoi
:rone suffit pas sont dans le guide dédié.
Enfin, la télémétrie est active par défaut et envoie chaque heure des
compteurs anonymes vers metrics.kolapsis.com. Elle est minimale et sans
identifiant d'hôte, mais pour un usage orienté souveraineté, le
MAINTENANT_DISABLE_TELEMETRY: "1" de notre compose la coupe dès le départ.
Modèle open-core et licence
Section intitulée « Modèle open-core et licence »Maintenant est sous licence AGPL-3.0, une licence libre reconnue par l'OSI qui impose de publier les modifications même en usage réseau. Le modèle est open-core : l'édition Community couvre la découverte, les sondes, les heartbeats, les certificats et la page de statut ; l'édition Pro (29 euros par mois) débloque le multi-hôte, l'escalade d'alertes, les canaux Slack/Teams et l'enrichissement CVE. Pour un mono-hôte, la version gratuite est autonome. Le multi-hôte, lui, est justement le besoin d'un prestataire qui gère plusieurs clients : c'est un arbitrage à intégrer avant d'adopter l'outil à grande échelle.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
health renvoie "connected":false | Le proxy n'est pas encore joignable | Attendre la reconnexion, vérifier docker compose logs socketproxy |
Le proxy boucle en Restarting | read_only avec une version 0.3.0 | Épingler l'empreinte de la v0.4.2 indiquée |
| Aucun conteneur découvert | DOCKER_HOST absent ou mauvais réseau | Vérifier que Maintenant est sur le réseau dockerapi |
Une sonde reste down sans raison | URL du label injoignable depuis le conteneur | Tester l'URL, vérifier que les deux services partagent un réseau |
| Interface accessible depuis le LAN sans mot de passe | Port publié trop largement | Repasser en 127.0.0.1:8899:8080 et ajouter un reverse proxy |
Limites connues
Section intitulée « Limites connues »Trois points méritent d'être connus avant d'adopter l'outil. D'abord, le bus-factor : le projet repose sur un seul mainteneur et reste jeune, ce qui est un risque pour une brique de supervision destinée à durer. Ensuite, l'absence de tag de version sur le registre d'images oblige à épingler par empreinte, ce que fait ce guide. Enfin, quelques valeurs par défaut documentées ne correspondent pas au comportement observé sur les sondes : fiez- vous à ce que renvoie l'API plutôt qu'à la table de documentation.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »:ro), donne un accès équivalent à root sur l'hôte : le drapeau :ro protège le fichier, pas l'API. Le proxy est la seule vraie frontière.maintenant.endpoint.http avec l'URL à vérifier, plus éventuellement maintenant.endpoint.interval. Maintenant détecte le label au démarrage du conteneur et commence la vérification automatiquement. La sonde vit ainsi avec le service qu'elle surveille.metrics.kolapsis.com. Les données sont anonymes et minimales (compteurs d'entités, système d'exploitation, version), sans nom d'hôte ni URL. On désactive la télémétrie en positionnant MAINTENANT_DISABLE_TELEMETRY à 1. Pour un usage orienté souveraineté, il est raisonnable de la couper dès l'installation.À retenir
Section intitulée « À retenir »- Maintenant est un moniteur Docker/Kubernetes en un binaire Go, avec découverte automatique et sondes en labels.
- Ne jamais monter le socket Docker dans le conteneur : un
socket proxy filtre l'API en lecture seule, et
DOCKER_HOSTsuffit. - Les sondes HTTP se déclarent en labels, pas dans l'interface, et suivent le cycle de vie du conteneur.
- Les heartbeats surveillent les tâches planifiées via une URL de ping à traiter comme un secret.
- Aucune authentification interne : garder le port en loopback et mettre un reverse proxy authentifié devant tout accès distant.
- AGPL-3.0, open-core : le mono-hôte est gratuit, le multi-hôte est en édition Pro. Couper la télémétrie pour un usage souverain.
Prochaines étapes
Section intitulée « Prochaines étapes »Plus d'infos
Section intitulée « Plus d'infos »- Dépôt GitHub : code source, issues et releases.
- Site officiel : présentation et documentation upstream.