Introduction
Docker Compose Watch offre aux développeurs une boucle de rétroaction rapide en reconstruisant et en redémarrant les services lorsque les fichiers sources changent. Mais dans tout projet non trivial, vous devez aussi savoir quand les choses tournent mal : un plantage de service, un échec de build, un montage mal configuré ou une limite de ressources. La surveillance et les alertes transforment Compose Watch en un composant fiable de votre flux de travail opérationnel.
Ce guide détaille une mise en œuvre pratique de la surveillance, des alertes, des tableaux de bord et de la réponse aux incidents pour Docker Compose Watch. Il suppose que vous êtes à l'aise avec les bases de Docker et Compose, et se concentre sur la couche opérationnelle : quoi surveiller, comment détecter les problèmes et comment réagir en toute sécurité. Chaque section comprend des commandes exactes, des extraits de configuration, des sorties attendues et des étapes de récupération.
L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier les résultats et documenter les chemins de récupération. Ne traitez pas ceci comme une liste de contrôle à copier-coller ; adaptez les exemples à votre environnement et à vos contraintes de version.
Inventaire des versions et de l'environnement
Avant de surveiller quoi que ce soit, sachez ce que vous exécutez. Une règle de surveillance qui suppose une mauvaise version ou topologie manquera des défaillances ou vous submergera de fausses alarmes.
Commencez par capturer vos versions actuelles de Docker et Compose. Exécutez :
docker version --format '{{.Server.Version}}'
docker compose version
Exemple de sortie attendue :
24.0.7
Docker Compose version v2.21.0
Ici, 24.0.7 est la version du moteur Docker et v2.21.0 est la version du plugin Compose. Compose Watch nécessite Docker Compose v2.17.0 ou ultérieur, et l'attribut watch n'est pleinement pris en charge qu'avec BuildKit et le format de fichier Compose v2 (généralement compose.yaml). Si vous voyez une version plus ancienne, mettez à niveau avant d'activer watch.
Ensuite, listez les services de votre projet Compose et leur état :
docker compose ps
Exemple de sortie :
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
project-web-1 project-web:latest "gunicorn app:app" web 2 minutes ago Up 2 minutes 0.0.0.0:8000->8000/tcp
project-db-1 postgres:15 "docker-entrypoint.s…" db 2 minutes ago Up 2 minutes 5432/tcp
Notez les noms de services (web, db), les noms de conteneurs et l'état de santé. Un Up manquant sous STATUS est le premier signal de défaillance.
Pour une inspection en lecture seule d'un conteneur suspect, utilisez :
docker inspect project-web-1 --format '{{json .State.Health}}'
Sortie attendue (si un healthcheck est défini) :
{"Status":"healthy","FailingStreak":0,"Log":[{"Start":"2024-01-01T00:00:00Z","End":"2024-01-01T00:00:05Z","ExitCode":0,"Output":"ok"}]}
Si aucun healthcheck n'est défini, le champ est null. Vous pourrez en ajouter un plus tard ; nous couvrons cela dans la section Vérification.
Enfin, confirmez que vos montages de volumes sont corrects avant toute modification. La perte de données est une défaillance courante de Compose. Utilisez :
docker inspect project-db-1 --format '{{json .Mounts}}'
Exemple de sortie :
[{"Type":"volume","Name":"project_pgdata","Source":"/var/lib/docker/volumes/project_pgdata/_data","Destination":"/var/lib/postgresql/data","Driver":"local","Mode":"z","RW":true}]
Cela montre un volume nommé lié à /var/lib/postgresql/data. Si vous attendiez un montage bind vers ./data, c'est une incohérence. La corriger avant un redémarrage évite des heures de débogage plus tard.
Chemin de configuration sûr
La section watch de votre fichier Compose contrôle la façon dont les modifications sont synchronisées. Une règle watch mal configurée peut provoquer des boucles de reconstruction infinies, un va-et-vient des conteneurs ou des synchronisations manquées. Voici une configuration de départ sûre :
services:
web:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
watch:
- action: sync
path: ./app
target: /app
ignore:
- node_modules/
- .venv/
- action: rebuild
path: requirements.txt
environment:
FLASK_ENV: development
Points clés :
- Utilisez
action: syncpour les répertoires où seul le contenu des fichiers change, pas les dépendances. - Utilisez
action: rebuildpour les fichiers manifestes commerequirements.txtou les modifications duDockerfile. - Incluez toujours une liste
ignorepour les grands répertoires générés (node_modules,.venv,__pycache__) afin de réduire la charge de synchronisation.
Pour vérifier que votre configuration watch est valide, exécutez :
docker compose config --quiet
Si la configuration est invalide, cette commande se termine avec un statut non nul et affiche des erreurs sur stderr. Exemple d'erreur de syntaxe :
yaml: line 10: did not find expected key
Corrigez l'indentation YAML avant de continuer.
Testez maintenant manuellement le chemin de synchronisation. Démarrez la pile :
docker compose up --build -d
Surveillez les journaux pour le message de démarrage du watcher :
docker compose logs -f web
Exemple de ligne de journal :
web-1 | [watch] watching /app for changes
Déclenchez une synchronisation en modifiant un fichier dans ./app, par exemple :
echo "print('hello')" >> app/main.py
Vous devriez voir le watcher journaliser le changement et synchroniser le fichier sans redémarrer le conteneur. Si au contraire le conteneur redémarre ou se reconstruit, vous avez le mauvais type d'action.
Vérification et diagnostics
Après avoir configuré watch, vérifiez que votre application se comporte correctement sous les actions de synchronisation et de reconstruction. La première étape consiste à définir un healthcheck à l'intérieur de votre service. Pour une application web Python, ajoutez à compose.yaml :
services:
web:
# ...
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
Ce healthcheck exécute curl -f contre un endpoint /health toutes les 10 secondes, considère le conteneur comme non sain après 3 échecs consécutifs, et attend 30 secondes avant de commencer les vérifications au démarrage.
Appliquez le changement et recréez le service :
docker compose up -d web
Vérifiez l'état de santé :
docker inspect --format='{{.State.Health.Status}}' project-web-1
Sortie attendue :
healthy
Si elle indique unhealthy, inspectez les journaux du healthcheck :
docker inspect --format='{{json .State.Health.Log}}' project-web-1 | jq
Cela montre chaque tentative de healthcheck avec les codes de sortie et la sortie. Une défaillance courante est que l'endpoint renvoie 404 parce que la route n'est pas définie.
Pour des diagnostics plus approfondis, attachez-vous à un conteneur en cours d'exécution sans l'arrêter :
docker compose exec web sh
Dans le conteneur, vérifiez que vos fichiers ont été correctement synchronisés :
ls -la /app
Comparez les horodatages avec vos fichiers hôtes. Si un fichier est manquant ou obsolète, la synchronisation watch ignore peut-être le bon chemin. Revérifiez vos motifs ignore et le chemin target.
Enfin, testez la persistance du système de fichiers du conteneur. Arrêtez le conteneur, recréez-le et voyez si les données survivent :
docker compose stop web
docker compose up -d web
docker compose exec web ls /app/data
Si le répertoire est vide, vos données ont été écrites dans le système de fichiers éphémère du conteneur. Déplacez ce chemin vers un volume ou un montage bind comme décrit dans la section inventaire.
Surveillance et métriques
Docker Compose Watch lui-même n'expose pas de métriques, mais vous pouvez surveiller les conteneurs et les événements watch en combinant les métriques intégrées de Docker avec des alertes basées sur les journaux. Cette section montre une configuration minimale utilisant cAdvisor, Prometheus et Alertmanager, le tout exécuté via Compose.
Ajoutez une pile de surveillance à votre compose.yaml :
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.2
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
depends_on:
- web
prometheus:
image: prom/prometheus:v2.47.2
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
depends_on:
- cadvisor
alertmanager:
image: prom/alertmanager:v0.26.0
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
Créez prometheus.yml avec une configuration de scrape pour cAdvisor :
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
Ajoutez une alerte de redémarrage de conteneur à alertrules.yml (chargé par Prometheus) :
groups:
- name: container-alerts
rules:
- alert: ContainerKilled
expr: time() - container_last_seen{name=~"project-web-.*"} > 60
for: 1m
labels:
severity: critical
annotations:
summary: "Container {{ $labels.name }} has been down for more than 1 minute"
Cette alerte se déclenche lorsqu'un conteneur correspondant à project-web-.* n'a pas été vu pendant 60 secondes, avec une période de grâce d'1 minute. Dans alertmanager.yml, routez les alertes vers un e-mail ou Slack.
Testez l'alerte en arrêtant le conteneur web :
docker compose stop web
En environ 2 minutes (60s de métrique plus la clause for d'1m), Prometheus affichera l'alerte dans http://localhost:9090/alerts, et Alertmanager enverra une notification.
Tableau de bord et visualisation
Un tableau de bord vous aide à repérer rapidement les anomalies. Utilisez Grafana pour visualiser les métriques de cAdvisor.
Ajoutez Grafana à votre pile Compose :
grafana:
image: grafana/grafana:10.1.5
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- grafana-storage:/var/lib/grafana
depends_on:
- prometheus
Démarrez la pile et accédez à Grafana sur http://localhost:3000 (connectez-vous avec admin / admin, changez-le immédiatement). Ajoutez Prometheus comme source de données avec l'URL http://prometheus:9090.
Créez un nouveau tableau de bord et ajoutez les panneaux suivants en utilisant des requêtes Prometheus :
- Utilisation CPU par conteneur :
rate(container_cpu_usage_seconds_total{name=~"project-.*"}[5m])
- Utilisation mémoire :
container_memory_usage_bytes{name=~"project-.*"}
- Nombre de redémarrages (critique pour les reconstructions déclenchées par watch) :
increase(container_restart_count{name=~"project-.*"}[1h])
- Utilisation du système de fichiers (la synchronisation watch peut remplir le disque) :
container_fs_usage_bytes{name=~"project-.*"}
Définissez des seuils d'alerte sur le tableau de bord. Par exemple, un nombre de redémarrages supérieur à 5 au cours de la dernière heure suggère une boucle de reconstruction watch ; enquêtez immédiatement.
Modes de défaillance et récupération
Voici les modes de défaillance courants avec Docker Compose Watch et comment les récupérer.
1. Le watch ne déclenche pas de synchronisations ou de reconstructions
Symptôme : Vous modifiez un fichier, mais le contenu du conteneur ne change pas ; aucune entrée de journal du watcher.
Cause : Généralement un chemin watch mal configuré ou un target manquant. Le chemin est relatif au fichier Compose, pas à la racine de l'hôte. De plus, le watcher peut ignorer le fichier à cause d'un motif ignore.
Diagnostic : Exécutez docker compose config --services pour vérifier les services et confirmer que la section watch est présente. Inspectez le système de fichiers du conteneur par rapport à l'hôte :
docker compose exec web sh -c 'stat /app/file.py'
stat host/path/file.py
Si les horodatages diffèrent et que le contenu du fichier est obsolète, la synchronisation ne se produit pas.
Récupération : Corrigez path et target pour qu'ils correspondent exactement. Supprimez les motifs d'ignore trop larges. Redémarrez le processus watch en exécutant docker compose watch au premier plan et observez les journaux.
2. Boucle de reconstruction infinie
Symptôme : Le conteneur se reconstruit et redémarre constamment, consommant du CPU et provoquant des temps d'arrêt.
Cause : Un fichier qui change pendant le processus de construction (par exemple, un artefact généré) est surveillé, de sorte que le watcher déclenche une autre construction.
Diagnostic : Vérifiez les journaux watch pour des actions de reconstruction fréquentes :
docker compose logs -f web | grep -i rebuild
Si vous voyez des reconstructions répétées, le fichier déclencheur change.
Récupération : Déplacez les fichiers générés hors du répertoire surveillé ou ajoutez-les à la liste ignore. Pour les manifestes, utilisez action: sync lorsque c'est possible si une reconstruction n'est pas nécessaire. Alternativement, utilisez un .dockerignore pour empêcher le fichier d'être copié dans le contexte de construction.
3. Le conteneur se termine après synchronisation en raison d'une dépendance manquante
Symptôme : Après une synchronisation, le conteneur se termine avec un code non nul.
Cause : Le fichier synchronisé référence une nouvelle bibliothèque qui n'est pas installée dans l'image car la synchronisation a eu lieu avant la reconstruction.
Diagnostic : Vérifiez le code de sortie du conteneur et les journaux :
docker inspect project-web-1 --format='{{.State.ExitCode}}'
docker logs project-web-1 --tail 50
Si l'erreur est un ModuleNotFoundError, la dépendance est manquante.
Récupération : Changez l'action watch en rebuild pour les fichiers qui modifient les dépendances, ou reconstruisez manuellement avec docker compose up --build web puis redémarrez le watch.
4. Perte de données après recréation du conteneur
Symptôme : L'application perd son état après une reconstruction déclenchée par watch.
Cause : Les données sont stockées dans la couche inscriptible du conteneur, qui est détruite lors de la reconstruction. Le service a écrit sur un chemin non sauvegardé par un volume ou un montage bind.
Diagnostic : Comparez les données avant et après reconstruction. Inspectez les montages :
docker inspect project-db-1 --format='{{json .Mounts}}'
Si le répertoire de données n'est pas listé, il est éphémère.
Récupération : Ajoutez un volume à la définition du service et migrez les données. Arrêtez le conteneur, copiez les données si possible, ajoutez le volume et redémarrez. À l'avenir, assurez-vous que tous les chemins avec état sont des volumes.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour chaque service activé par watch avant et pendant le développement. Attribuez un responsable par élément pour éviter toute ambiguïté.
| # | Élément de la liste | Responsable | Comment vérifier | Fréquence de révision |
|---|---|---|---|---|
| 1 | Confirmer que les versions de Docker et Compose répondent aux exigences minimales | Développeur principal (par ex., Priya Shah) | Exécuter docker compose version ; comparer aux requis | À chaque version |
| 2 | Examiner la configuration watch pour les chemins et les motifs d'ignore corrects | Ingénieur DevOps (par ex., Marcus Chen) | docker compose config --quiet ; test manuel de synchronisation | Hebdomadaire |
| 3 | S'assurer que des healthchecks sont définis pour tous les services avec état | Responsable backend (par ex., Ana Lopez) | docker inspect --format='{{.State.Health.Status}}' | À chaque PR |
| 4 | Vérifier la persistance des données avec un test de redémarrage | Ingénieur QA (par ex., Tom Nguyen) | Arrêter, recréer, vérifier que les données existent | Avant chaque déploiement |
| 5 | Surveiller les compteurs de redémarrage pour les boucles de reconstruction | SRE (par ex., Jordan Patel) | Requête Prometheus increase(container_restart_count[1h]) | Quotidien |
| 6 | Tester le routage des alertes de bout en bout | Ingénieur d'astreinte (rotation) | Déclencher une alerte de test, confirmer la notification | Mensuel |
| 7 | Examiner les performances de synchronisation et de reconstruction (CPU, E/S disque) | Ingénieur DevOps | Tableau de bord Grafana ; vérifier les métriques cAdvisor | Hebdomadaire |
Note sur la responsabilité : Le développeur principal est responsable de la configuration globale du watch et des définitions des actions watch. L'ingénieur DevOps est responsable de l'infrastructure de surveillance et d'alerte. Révisez la liste de contrôle lors d'une réunion hebdomadaire et mettez à jour les responsables si la composition de l'équipe change.
Contrôle des modifications : Toute modification de la section watch ou des règles de surveillance doit passer par une pull request avec une révision par au moins un autre ingénieur. Après fusion, exécutez les étapes de vérification ci-dessus et consignez les résultats dans le journal de déploiement.
Pièges courants
Évitez ces erreurs qui piègent fréquemment les équipes utilisant Compose Watch.
- Surveiller trop de fichiers - Inclure un grand répertoire comme
node_modulesdans le chemin de synchronisation peut submerger le watcher et provoquer des retards. Définissez toujours des motifs d'ignore. Exemple : ignorez*/.log,/__pycache__,/node_modules.
- Confondre synchronisation et reconstruction - Utiliser
rebuildpour chaque changement va à l'encontre du but de watch ; utilisersyncpour les changements de dépendances laisse le conteneur dans un état cassé. Utilisezsyncpour les fichiers sources,rebuildpour les manifestes et les modifications du Dockerfile.
- Ne pas définir de limites de ressources - Les reconstructions pilotées par watch peuvent faire grimper le CPU et la mémoire. Définissez
deploy.resources.limitspour les services en développement afin d'éviter de déstabiliser l'hôte :
services:
web:
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
- Ignorer les journaux du watch - Le watcher émet des informations utiles sur ce qu'il fait. Exécutez
docker compose logs -fdans un terminal séparé pendant le développement ; ne les silencez pas.
- Supposer que watch fonctionne en production - Compose Watch est conçu pour le développement. En production, utilisez des images immuables et l'orchestration. Si vous devez l'utiliser pour des déploiements à petite échelle, désactivez watch avec
docker compose up(paswatch) et surveillez de près.
- Coder en dur des secrets dans du code déclenché par watch - Une synchronisation peut copier des fichiers contenant des secrets dans le conteneur. Utilisez des variables d'environnement et des montages de secrets ; ne commitez jamais de secrets dans le dépôt.
Conclusion
Docker Compose Watch peut considérablement accélérer le développement, mais ce n'est pas un outil à configurer et oublier. Une surveillance et des alertes efficaces exigent de comprendre votre environnement, de configurer correctement les actions watch, de vérifier l'état du conteneur après chaque modification et de se préparer aux défaillances.
Commencez par les sections inventaire et configuration sûre, puis ajoutez des healthchecks et des métriques. La liste de contrôle opérationnelle et les pièges courants fournissent un cadre pour maintenir votre configuration Compose Watch saine au fil du temps. N'oubliez pas de réviser régulièrement les seuils d'alerte et les attributions de responsabilité, car les applications et les équipes évoluent.
Comme prochaine étape, mettez en œuvre un aspect de surveillance de ce guide : définissez un healthcheck pour votre service le plus critique, configurez une alerte de redémarrage ou créez un panneau de tableau de bord pour les compteurs de redémarrage. Documentez l'état actuel, exécutez la vérification et comparez avec le signal attendu. Ensuite, étendez au reste de votre pile. Une surveillance fiable du watch rend le développement plus rapide et plus sûr.