## Introduction Quand un conteneur plante en production à 3 h du matin, la différence entre un incident mineur et une panne complète tient souvent à un seul paramètre : la politique de redémarrage. Les politiques de redémarrage Docker déterminent si un conteneur redémarre automatiquement après sa sortie, et dans quelles conditions. Si vous les configurez mal, vous aurez soit des services qui restent silencieusement arrêtés, soit des conteneurs qui redémarrent sans fin, masquant des problèmes plus profonds. Cet article constitue une liste de contrôle opérationnelle pratique pour utiliser les politiques de redémarrage Docker en production. Il s'adresse aux développeurs, consultants DevOps et équipes de startup qui doivent passer d'un problème observé à un résultat vérifié. Vous y trouverez des commandes concrètes, des sorties attendues, des extraits de configuration et des conseils de récupération. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des variables fictives plutôt que des secrets, vérifier le résultat et documenter la façon de récupérer si l'état attendu n'est pas atteint. Nous aborderons les quatre politiques de redémarrage (`no`, `on-failure`, `unless-stopped`, `always`), montrerons comment les définir via la CLI Docker et Docker Compose, expliquerons comment les inspecter et les tester, soulignerons les erreurs courantes et fournirons une liste de contrôle utilisable en production. ## Comprendre les politiques de redémarrage Docker Les politiques de redémarrage Docker contrôlent si un conteneur est automatiquement redémarré après son arrêt ou sa sortie. La politique est attachée au conteneur au moment de sa création et s'applique à la fois aux sorties normales et aux plantages, selon la politique. Les quatre politiques intégrées sont : | Politique | Comportement | Cas d'utilisation typique | |---|---|---| | `no` | Ne jamais redémarrer automatiquement. | Tâches ponctuelles, conteneurs de débogage. | | `on-failure[:max-retries]` | Redémarrer uniquement si le conteneur sort avec un code non nul. Limite éventuelle du nombre de tentatives. | Services susceptibles de planter mais qui ne doivent pas réessayer indéfiniment. | | `always` | Toujours redémarrer, même si le conteneur s'arrête proprement. Redémarre aussi au démarrage du démon. | Services à longue durée de vie qui doivent toujours être actifs. | | `unless-stopped` | Toujours redémarrer, sauf si le conteneur a été arrêté manuellement par un opérateur. Redémarre au démarrage du démon s'il était en cours d'exécution auparavant. | Services qui doivent rester actifs, sauf arrêt délibéré. | Comprendre ces politiques est la base. Les sections suivantes vous donnent un moyen systématique de les inspecter, de les définir et de les vérifier dans votre environnement. ## Inventaire des versions et de l'environnement Avant de toucher à une politique de redémarrage, vous devez savoir avec quoi vous travaillez. Un inventaire des versions et de l'environnement est la première étape de toute opération sûre. Il nomme le composant concerné, la plage de versions prises en charge, les prérequis et une observation en lecture seule. **Vérifier la version de Docker.** Les politiques de redémarrage existent depuis des années, mais la syntaxe et le comportement peuvent varier légèrement. Exécutez : ```bash docker version --format '{{.Server.Version}}' ``` Exemple de sortie attendue : ``` 24.0.5 ``` Vérifiez aussi la version de l'API si vous utilisez une bibliothèque cliente : ```bash docker version --format '{{.Server.APIVersion}}' ``` **Lister les conteneurs en cours d'exécution et leur statut.** Utilisez une sortie formatée pour voir les noms, statuts et ports : ```bash docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" ``` Exemple de sortie : ``` NAMES STATUS PORTS web Up 3 hours 0.0.0.0:80->80/tcp api Restarting (1) 2 seconds ago 0.0.0.0:8080->8080/tcp ``` Remarquez que le conteneur `api` affiche `Restarting (1) 2 seconds ago`. Cela indique qu'il a planté une fois et qu'il est redémarré par une politique. C'est une observation clé. **Inspecter la politique de redémarrage d'un conteneur.** Utilisez `docker inspect` pour voir la politique actuelle et d'autres détails : ```bash docker inspect --format '{{.HostConfig.RestartPolicy.Name}} {{.HostConfig.RestartPolicy.MaximumRetryCount}}' ``` Pour un conteneur avec `on-failure:5`, la sortie serait : ``` on-failure 5 ``` **Vérifier les journaux pour détecter des schémas de plantage.** Lisez les journaux récents pour comprendre pourquoi un conteneur redémarre : ```bash docker logs --tail 100 ``` **Pour les projets Docker Compose**, utilisez `docker compose ps` et `docker compose logs` de manière similaire. Les services Compose peuvent avoir des politiques de redémarrage définies dans le fichier compose, qui remplacent les valeurs par défaut. **Vérification de la persistance des données.** Lorsque vous modifiez les politiques de redémarrage ou recréez des conteneurs, assurez-vous que les données persistent. Confirmez où les fichiers sont stockés : ```bash docker inspect --format '{{json .Mounts}}' ``` Recherchez `Type: volume` (volume nommé) ou `Type: bind` (chemin hôte). Un volume nommé comme `app_data:/var/lib/app` est géré par Docker et survit à la recréation du conteneur. Un montage bind comme `./data:/var/lib/app` mappe directement un répertoire hôte, ce qui est utile pour le développement mais peut causer des problèmes de permissions ou de portabilité si le chemin diffère d'une machine à l'autre. **Test pratique :** Arrêtez le conteneur, recréez-le sans changer l'image et vérifiez que l'application voit toujours les fichiers attendus. Si les données disparaissent, le service écrivait dans la couche inscriptible du conteneur au lieu d'un volume. C'est un problème distinct à corriger avant de dépendre des politiques de redémarrage. Avec cet inventaire, vous connaissez vos versions, les politiques actuelles et la disposition des données. Vous pouvez maintenant configurer les politiques en toute sécurité. ## Chemin de configuration sûr Modifier une politique de redémarrage est généralement peu risqué, mais le faire négligemment peut entraîner un comportement inattendu. Le chemin de configuration sûr implique de choisir la bonne politique, de l'appliquer de manière idempotente et de vérifier le changement. ### Choisir la bonne politique Posez deux questions : 1. Le conteneur doit-il redémarrer tout seul ? 2. Doit-il redémarrer même après un arrêt propre ? Utilisez ce guide de décision : | Situation | Politique recommandée | |---|---| | Tâche batch ponctuelle ou shell interactif | `no` | | Conteneur cron-like avec nouvelle tentative interne | `no` ou `on-failure` | | Serveur web ou API qui doit toujours fonctionner | `always` ou `unless-stopped` | | Service qui ne doit pas redémarrer après un arrêt délibéré (par exemple, maintenance) | `unless-stopped` | | Service qui doit réessayer uniquement en cas de plantage, avec une limite pour éviter les boucles de plantage | `on-failure:5` | ### Appliquer une politique via la CLI Docker Pour un conteneur existant, vous ne pouvez pas modifier directement la politique de redémarrage. Vous devez recréer le conteneur avec la nouvelle politique. Utilisez `docker update` pour certaines limites de ressources, mais la politique de redémarrage n'en fait pas partie. Exemple : recréer un conteneur nommé `web` avec `unless-stopped` : ```bash # Arrêter et supprimer le conteneur existant (attention : assurez-vous que les données sont sur un volume) docker rm -f web # Exécuter un nouveau conteneur avec la politique docker run -d --name web --restart unless-stopped -p 80:80 nginx:alpine ``` Vérifiez : ```bash docker inspect web --format '{{.HostConfig.RestartPolicy.Name}}' ``` Sortie : ``` unless-stopped ``` ### Appliquer une politique via Docker Compose Dans un fichier `docker-compose.yml`, définissez la clé `restart` sous un service : ```yaml services: web: image: nginx:alpine restart: unless-stopped ports: - "80:80" ``` Appliquez avec : ```bash docker compose up -d ``` Compose recréera les conteneurs qui nécessitent la nouvelle politique. Pour forcer la recréation : ```bash docker compose up -d --force-recreate ``` ### Tester la politique localement Ne déployez pas une politique non testée. Simulez un plantage et observez le comportement. Pour `on-failure`, créez un conteneur qui sort avec une erreur après quelques secondes : ```bash docker run -d --name test-fail --restart on-failure:2 alpine sh -c "sleep 5; exit 1" ``` Surveillez le statut avec : ```bash docker ps -a --filter name=test-fail ``` Après environ 15 secondes, vous devriez voir : ``` CONTAINER ID STATUS NAMES abc123 Exited (1) 2 minutes ago test-fail ``` Le conteneur a tenté de redémarrer deux fois (à cause de `:2`) puis s'est arrêté définitivement. Vérifiez les journaux pour confirmer : ```bash docker logs test-fail ``` Pour `always`, créez un conteneur qui sort immédiatement : ```bash docker run -d --name test-always --restart always alpine sh -c "exit 0" ``` En quelques secondes, `docker ps -a` le montrera dans une boucle de redémarrage : ``` CONTAINER ID STATUS NAMES abc456 Restarting (0) 1 second ago test-always ``` Arrêtez-le manuellement : ```bash docker stop test-always ``` Vérifiez ensuite : il ne doit pas être redémarré car le démon le considère comme arrêté manuellement. Mais si vous redémarrez le démon Docker, `always` le redémarrera, tandis que `unless-stopped` ne le fera pas (car il a été arrêté manuellement avant le redémarrage du démon). Testez `unless-stopped` en arrêtant un conteneur, en redémarrant le démon Docker et en confirmant que le conteneur reste arrêté. Ces tests vous donnent confiance dans le comportement de la politique avant la production. ## Vérification et diagnostic Après avoir défini une politique, vous devez vérifier qu'elle fonctionne comme prévu. Cette section donne un moyen systématique d'observer, diagnostiquer et confirmer le comportement de redémarrage. ### Observer l'état actuel du redémarrage Utilisez `docker ps` pour voir si un conteneur est en cours de redémarrage : ```bash docker ps --filter "status=restarting" ``` Vérifiez aussi le nombre de redémarrages d'un conteneur : ```bash docker inspect --format '{{.RestartCount}}' ``` Par exemple, si un conteneur a redémarré 12 fois en une heure, quelque chose ne va pas. Comparez avec les journaux : ```bash docker logs --tail 50 ``` ### Diagnostiquer les boucles de plantage Un conteneur dans une boucle de redémarrage (par exemple, `Restarting (1) 5 seconds ago`) indique que la politique fait son travail mais que l'application échoue de manière répétée. Pour interrompre temporairement la boucle et enquêter : 1. Arrêtez le conteneur (cela outrepasse `always` et `unless-stopped` jusqu'au redémarrage du démon) : ```bash docker stop ``` 2. Inspectez le système de fichiers du conteneur ou exécutez une commande ponctuelle pour déboguer. Par exemple, lancez un shell interactif dans la même image : ```bash docker run -it --rm --entrypoint sh ``` 3. Vérifiez les journaux du conteneur arrêté sans le redémarrer : ```bash docker logs ``` 4. Une fois corrigé, redémarrez le conteneur : ```bash docker start ``` ### Vérifier la persistance de la politique lors des redémarrages du démon Les politiques de redémarrage interagissent avec le démon Docker. Après un redémarrage du démon, les conteneurs avec `always` sont démarrés quel que soit leur état avant l'arrêt du démon. Les conteneurs avec `unless-stopped` ne sont démarrés que s'ils étaient en cours d'exécution avant l'arrêt du démon. Pour tester cela de manière contrôlée : 1. Créez deux conteneurs : l'un avec `always`, l'autre avec `unless-stopped`. 2. Arrêtez manuellement les deux. 3. Redémarrez le démon Docker (`sudo systemctl restart docker` sur Linux). 4. Vérifiez `docker ps -a` : - Le conteneur `always` sera en cours d'exécution. - Le conteneur `unless-stopped` restera arrêté. Sortie attendue après le redémarrage du démon : ``` CONTAINER ID STATUS NAMES def789 Up 10 seconds test-always ghi012 Exited (0) test-unless-stopped ``` C'est une distinction opérationnelle importante. ### Surveiller les événements de redémarrage Pour la production, vous devez surveiller le nombre de redémarrages et les événements. Docker émet des événements que vous pouvez observer : ```bash docker events --filter container= --filter event=die ``` Cela diffuse des événements comme : ``` 2023-09-01T10:00:00.123456789Z container die abc123 (exitCode=1, image=nginx:alpine, name=web) ``` Vous pouvez également utiliser `docker inspect --format` dans un script cron ou de surveillance pour alerter lorsque le nombre de redémarrages augmente rapidement. ## Modes de défaillance et récupération Même avec des politiques correctes, des défaillances surviennent. Cette section couvre les modes de défaillance courants avec les politiques de redémarrage et comment récupérer. **Boucle de plantage due à un bug applicatif.** La politique redémarre le conteneur, mais il continue de planter. Cela n'est pas résolu par la politique seule ; vous devez corriger l'application. Récupération : arrêtez le conteneur pour interrompre la boucle, déboguez avec les journaux et un shell, corrigez le code ou la configuration, et redéployez. Utilisez `on-failure` avec une limite de tentatives pour éviter des boucles sans fin qui consomment du CPU et masquent les problèmes. **Perte de données causée par la recréation du conteneur.** Si vous recréez un conteneur pour modifier sa politique de redémarrage sans volumes appropriés, vous pouvez perdre des données écrites à l'intérieur du conteneur. Récupération : mettez en place un volume ou un montage bind avant la recréation, et testez la persistance des données comme décrit précédemment. Si les données sont déjà perdues, restaurez à partir d'une sauvegarde si disponible. **Politique de redémarrage trop agressive.** Une politique `always` sur un conteneur qui sort immédiatement peut provoquer une boucle de redémarrage serrée, remplissant les journaux et consommant des ressources. Récupération : arrêtez le conteneur, modifiez la commande pour le maintenir en cours d'exécution ou corrigez la raison de la sortie, puis redémarrez. Envisagez `on-failure` avec une limite de tentatives. **Politique de redémarrage non appliquée comme prévu.** Vous pensez avoir modifié la politique, mais le conteneur affiche toujours l'ancienne. Cela arrive souvent parce que vous avez utilisé `docker update` (qui ne prend pas en charge la politique de redémarrage) ou modifié un fichier compose sans recréer le conteneur. Récupération : vérifiez la politique réelle avec `docker inspect`, puis recréez le conteneur avec la bonne politique. **Redémarrage du démon provoquant des démarrages de conteneurs inattendus.** Si vous avez des conteneurs avec `always`, un redémarrage planifié du démon les démarrera même s'ils ont été intentionnellement arrêtés. Cela peut surprendre les opérateurs. Récupération : utilisez `unless-stopped` pour les conteneurs qui doivent respecter les arrêts manuels. **La politique de redémarrage interfère avec l'orchestration.** Dans Docker Swarm ou Kubernetes, la politique de redémarrage des conteneurs est gérée par l'orchestrateur ; définir `restart` dans la spécification du conteneur peut entrer en conflit. Récupération : utilisez le mécanisme de redémarrage de l'orchestrateur (par exemple, `restart_policy` de Swarm sous la spécification de service, `restartPolicy` de pod Kubernetes). Ne définissez pas de politiques au niveau des conteneurs pour les charges de travail orchestrées. Chaque mode de défaillance doit être documenté dans votre runbook avec des symptômes spécifiques et des étapes de récupération. ## Liste de contrôle opérationnelle Voici une liste de contrôle axée sur la production pour gérer les politiques de redémarrage Docker. Chaque élément inclut le rôle responsable et la fréquence de révision. ### 1. Inventaire et audit (Propriétaire : ingénieur plateforme, révisé trimestriellement) - [ ] Lister tous les conteneurs en cours d'exécution et leurs politiques de redémarrage : ```bash docker ps --format "table {{.Names}}\t{{.Status}}\t{{.HostConfig.RestartPolicy.Name}}" ``` Remarque : `{{.HostConfig.RestartPolicy.Name}}` peut ne pas être directement disponible dans `docker ps` ; utilisez `docker inspect` dans une boucle : ```bash for c in $(docker ps -q); do echo -n "$c "; docker inspect $c --format '{{.Name}} {{.HostConfig.RestartPolicy.Name}}'; done ``` - [ ] Vérifier que chaque service critique a une politique appropriée (par exemple, `unless-stopped` pour les services à longue durée de vie, `on-failure:5` pour les services sujets aux plantages mais récupérables). - [ ] Vérifier les compteurs de redémarrage pour des valeurs anormales : ```bash docker inspect --format '{{.RestartCount}}' ``` Si le compteur est supérieur à 10 en 24 heures, enquêter. ### 2. Sélection de la politique (Propriétaire : propriétaire de l'application, révisé à chaque déploiement) - [ ] Pour chaque service, décider entre `no`, `on-failure`, `always`, `unless-stopped` en fonction du cycle de vie attendu. - [ ] Documenter la justification dans le runbook du service. - [ ] Pour `on-failure`, définir une limite de tentatives raisonnable pour éviter les boucles sans fin. ### 3. Implémentation (Propriétaire : ingénieur DevOps, exécuté à chaque changement) - [ ] Pour la CLI Docker, recréer le conteneur avec `--restart `. - [ ] Pour Compose, ajouter `restart:` à la définition du service et exécuter `docker compose up -d`. - [ ] Utiliser `docker inspect` pour confirmer que la politique est appliquée. ### 4. Tests (Propriétaire : responsable QA/release, exécuté à chaque release) - [ ] Effectuer un test de redémarrage local : créer un conteneur avec la politique, simuler une défaillance ou un arrêt manuel, observer le comportement. - [ ] Tester l'interaction avec le redémarrage du démon pour `always` et `unless-stopped`. - [ ] Vérifier la persistance des données lors de la recréation du conteneur. ### 5. Surveillance (Propriétaire : SRE/astreinte, continu) - [ ] Mettre en place des alertes pour une augmentation rapide du nombre de redémarrages (par exemple, via le flux `docker events` ou un outil de surveillance). - [ ] Journaliser tous les événements de redémarrage pour l'analyse post-incident. - [ ] Inclure les vérifications de politique de redémarrage dans les contrôles de santé réguliers. ### 6. Runbook de récupération (Propriétaire : commandant d'incident, révisé mensuellement) - [ ] Documenter les étapes pour arrêter une boucle de plantage. - [ ] Documenter les étapes pour récupérer d'une perte de données accidentelle. - [ ] Documenter comment modifier une politique sur un service en cours d'exécution sans provoquer d'indisponibilité. Cette liste de contrôle doit être intégrée à vos flux de travail opérationnels existants. ## Pièges courants et comment les éviter Même les utilisateurs Docker expérimentés commettent des erreurs avec les politiques de redémarrage. Voici les plus courantes et comment les éviter. **Piège 1 : Utiliser `always` pour des tâches de courte durée.** Une tâche batch qui se termine avec succès sera redémarrée indéfiniment, consommant des ressources. Utilisez `no` ou `on-failure` pour de tels conteneurs. Si vous avez besoin d'une tâche périodique, utilisez un planificateur externe (par exemple, cron sur l'hôte) pour exécuter un nouveau conteneur à chaque fois. **Piège 2 : Oublier que `always` outrepasse les arrêts manuels lors du redémarrage du démon.** Vous arrêtez un conteneur pour maintenance, puis redémarrez Docker, et il revient. Utilisez `unless-stopped` si vous voulez que les arrêts manuels persistent lors des redémarrages du démon. **Piège 3 : Ne pas définir de limite de tentatives pour `on-failure`.** Sans limite, un conteneur peut redémarrer éternellement, masquant la cause racine. Définissez `on-failure:5` ou similaire pour abandonner après quelques tentatives, forçant une enquête. **Piège 4 : Essayer de modifier la politique de redémarrage avec `docker update`.** `docker update` peut modifier les limites de ressources mais pas la politique de redémarrage. Vous devez recréer le conteneur. Vérifiez toujours avec `docker inspect`. **Piège 5 : Ignorer les pics du compteur de redémarrages.** Un compteur de redémarrages élevé est un symptôme d'un service instable. Surveillez-le et alertez en cas d'augmentation anormale. **Piège 6 : Appliquer des politiques de redémarrage au niveau des conteneurs dans des environnements orchestrés.** Dans Docker Swarm ou Kubernetes, l'orchestrateur gère les redémarrages. Définir des politiques au niveau des conteneurs peut entrer en conflit. Utilisez les spécifications de redémarrage de l'orchestrateur. **Piège 7 : Ne pas tester la persistance des données avant de modifier la politique de redémarrage.** Si vous recréez un conteneur pour modifier la politique et n'avez pas configuré de volumes, vous pouvez perdre des données. Testez toujours avec des volumes. En étant conscient de ces pièges, vous pouvez éviter la plupart des problèmes liés aux politiques de redémarrage. ## Conclusion Les politiques de redémarrage Docker sont une partie petite mais critique des opérations de conteneurs en production. Une politique bien configurée garantit que vos services récupèrent automatiquement des plantages sans masquer des problèmes plus profonds. Cet article a fourni une liste de contrôle pratique et des exemples pour définir, vérifier et dépanner les politiques de redémarrage. Rappelez-vous les principes de sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des variables fictives plutôt que des secrets, vérifier le résultat et documenter les étapes de récupération. Appliquez la liste de contrôle à votre environnement, adaptez-la à vos services et révisez-la régulièrement. Comme prochaine étape, choisissez un conteneur dans votre environnement de production, vérifiez sa politique de redémarrage par rapport aux directives de cet article et exécutez un test local pour confirmer le comportement attendu. Ensuite, étendez l'audit à tous les services critiques. Avec ces pratiques, vous serez mieux préparé pour ces plantages de 3 h du matin.