## Introduction Les secrets Docker offrent un moyen intégré de gérer les mots de passe, les clés API, les certificats et autres données sensibles sans les intégrer dans les images ni les variables d’environnement. Dans Docker Swarm, les secrets sont chiffrés pendant le transit et au repos, et ne sont montés que dans les conteneurs explicitement autorisés à y accéder. Le stockage est simple. Les problèmes surviennent généralement lorsqu’un service tente d’accéder au montage du secret ou de communiquer avec un autre service qui dépend de ces secrets, et qu’un problème réseau se met en travers. Ce guide est une présentation pratique pour ces moments-là. Nous aborderons la résolution DNS dans le réseau overlay, la connectivité des ports entre services, le comportement du routage entre nœuds, les règles de pare-feu qui bloquent silencieusement le trafic Swarm, et les commandes de diagnostic sûres à exécuter sans interrompre la production. Vous repartirez avec un processus reproductible : établir une base de référence, inspecter la configuration, tester chaque couche, isoler la panne et récupérer avec un plan de retour en arrière. ## Inventaire des versions et de l’environnement Avant de modifier quoi que ce soit, sachez avec quoi vous travaillez. Les incompatibilités de versions et les mauvaises configurations de nœuds sont des causes profondes fréquentes, et vous voulez les écarter tôt. ### Vérifier les versions de Docker et de Swarm Exécutez ceci sur un nœud manager : ```bash docker version --format '{{.Server.Version}}' ``` Sortie attendue : ```text 20.10.17 ``` Confirmez maintenant que le nœud est un manager et que le Swarm est sain : ```bash docker info --format '{{.Swarm.LocalNodeState}} {{.Swarm.ControlAvailable}}' ``` Sortie attendue : ```text active true ``` Si l’état local du nœud n’est pas `active`, ou si le contrôle n’est pas disponible, vous n’êtes pas sur un nœud manager. Toutes les commandes de gestion `docker service` et `docker network` doivent s’exécuter sur un manager. ### Lister les nœuds et les réseaux Obtenez une vue d’ensemble du cluster : ```bash docker node ls ``` Recherchez les nœuds avec le statut `Ready` et la disponibilité `Active`. Un nœud à l’état `Down` ou `Drain` peut expliquer des réplicas de service manquants ou des conteneurs inaccessibles. Listez ensuite les réseaux : ```bash docker network ls ``` Faites attention au driver et à la portée. Les réseaux overlay de Docker Swarm utilisent le driver `overlay` et ont une portée `swarm`. Un réseau créé avec le driver `bridge` est local à un seul nœud et ne routera pas le trafic entre conteneurs sur des hôtes différents. ### Prérequis pour le dépannage - Accès SSH à au moins un nœud manager et à tout nœud worker où le service est planifié. - Permissions d’exécuter les commandes `docker`, généralement via `sudo` ou l’appartenance au groupe `docker`. - Un modèle mental de base des services Swarm, des tâches et du réseau overlay. - Un service ou une pile de test qui reproduit le problème sans toucher aux données de production. ## Chemin de configuration sûr Lorsqu’un service ne peut pas atteindre un secret ou un autre service, la tentation est de supprimer et de recréer le réseau, ou de redémarrer toute la pile. Résistez. Des modifications ciblées et réversibles vous permettent d’isoler le problème sans dommages collatéraux. ### Inspecter la configuration du service D’abord, voyez comment le service est défini : ```bash docker service inspect --pretty ``` Recherchez les rattachements réseau et les montages de secrets. Voici un exemple tronqué d’un service réel : ```text Networks: frontend-overlay Secrets: db_password Target: /run/secrets/db_password ``` Le chemin cible du secret est le chemin du fichier à l’intérieur du conteneur. Si l’application attend le secret à un emplacement différent, elle échouera même si le secret existe. Inspectez maintenant le réseau lui-même : ```bash docker network inspect --verbose ``` Cela montre le sous-réseau, la passerelle et les conteneurs attachés à ce réseau. Vérifiez que le conteneur du service est listé. S’il ne l’est pas, le service n’est pas sur ce réseau, quoi que dise la spécification du service. ### Ajouter un service de test sur le même réseau Pour tester le comportement réseau depuis l’intérieur de l’overlay, créez un service temporaire attaché au même réseau : ```bash docker service create --name test-secret-net --network alpine sleep 3600 ``` Cela crée un seul réplica d’un conteneur Alpine qui dort pendant une heure, vous laissant le temps d’exécuter les diagnostics. Obtenez l’ID du conteneur : ```bash docker ps -q --filter name=test-secret-net ``` Puis exécutez une commande dedans : ```bash docker exec -it $(docker ps -q --filter name=test-secret-net) sh ``` Dans le conteneur, testez l’accès au secret si le service testé est censé en avoir un : ```bash cat /run/secrets/my-secret ``` Si le fichier est absent, le secret n’est pas monté. C’est un problème de configuration, pas nécessairement un problème réseau, mais il apparaît souvent en même temps que les problèmes réseau parce que le service ne peut pas démarrer et ne rejoint donc jamais le réseau correctement. ### Isoler les problèmes DNS Le serveur DNS intégré de Docker tourne à `127.0.0.11` dans chaque conteneur. Il résout les noms de service en adresses IP virtuelles (VIP) sur le réseau overlay. Testez la résolution dans le conteneur de test : ```bash nslookup ``` La sortie attendue inclut la VIP : ```text Name: Address: 10.0.0.2 ``` Si la résolution échoue, vérifiez que le service est attaché au même réseau que le conteneur de test. La résolution DNS ne fonctionne que pour les services sur le même réseau overlay. Vérifiez aussi que le serveur DNS est accessible : ```bash cat /etc/resolv.conf ``` Il devrait afficher `nameserver 127.0.0.11`. S’il affiche un serveur DNS externe, quelque chose ne va pas dans la configuration réseau du conteneur. ## Vérification et diagnostics Travaillez maintenant systématiquement à travers chaque couche : DNS, ports, routage et pare-feu. Chaque test soit innocente une couche, soit pointe vers le coupable. ### Tests de résolution DNS Dans le conteneur de test, utilisez `dig` ou `nslookup` pour interroger le nom du service. Pour un service appelé `my-web` sur le réseau `frontend` : ```bash dig my-web +short ``` Résultat attendu : ```text 10.0.0.2 ``` Si le service est attaché à plusieurs réseaux, le serveur DNS renvoie une VIP par réseau. Interrogez avec le nom complet avec la portée du réseau si nécessaire : ```bash dig my-web.frontend +short ``` Vous pouvez aussi vérifier directement la VIP du service : ```bash docker service inspect my-web --format '{{json .Endpoint.VirtualIPs}}' ``` Cela montre la VIP par réseau, par exemple : ```json [{"NetworkID":"abcd1234","Addr":"10.0.0.2/24"}] ``` Si le DNS échoue, le service peut ne pas avoir de réplicas en cours d’exécution, ou le service n’est pas sur le même réseau. ### Connectivité des ports Une fois que le DNS fonctionne, testez si le port TCP est ouvert. La commande `nc` (netcat) est disponible dans de nombreuses images, ou vous pouvez l’installer dans le conteneur de test : ```bash apk add --no-cache netcat-openbsd ``` Testez ensuite la connectivité : ```bash nc -zv my-web 80 ``` Sortie attendue : ```text my-web (10.0.0.2:80) open ``` Si le port est fermé, vérifiez si le service publie réellement le port. Pour la communication interne de service à service, le service n’a pas besoin de publier un port avec `--publish` ; il lui suffit d’écouter sur le port à l’intérieur du conteneur. Inspectez la configuration des ports du service : ```bash docker service inspect my-web --format '{{json .Endpoint.Ports}}' ``` Si aucun port n’est listé, le service n’expose aucun port vers le monde extérieur, mais il peut toujours écouter en interne. Pour voir ce que fait le processus à l’intérieur du conteneur, exécutez une commande dans l’un des conteneurs du service : ```bash docker exec netstat -tulpn ``` Recherchez le port attendu à l’état `LISTEN`. ### Vérifications du routage Le routage IP de base peut être testé avec `ping`. Depuis le conteneur de test : ```bash ping -c 4 my-web ``` Si vous recevez des réponses, le routage IP fonctionne. Si le ping échoue, ne concluez pas immédiatement à un problème de routage : de nombreuses images de production désactivent l’écho ICMP, ou des règles de pare-feu bloquent le ping. Utilisez `traceroute` pour voir le chemin : ```bash traceroute my-web ``` Dans le réseau overlay, vous devriez voir une route directe vers la VIP sans sauts intermédiaires, car la VIP est gérée par le maillage de routage local. Pour un aperçu plus approfondi de la configuration réseau du conteneur : ```bash ip addr show ip route ``` Vérifiez que la passerelle par défaut correspond à la passerelle du réseau overlay. Vous pouvez obtenir la passerelle avec `docker network inspect` : ```bash docker network inspect frontend-overlay --format '{{json .IPAM.Config}}' ``` Exemple de sortie : ```json [{"Subnet":"10.0.0.0/24","Gateway":"10.0.0.1"}] ``` Si la route par défaut du conteneur pointe ailleurs, le conteneur peut avoir démarré avec une mauvaise configuration réseau. ### Vérifications du pare-feu Les règles de pare-feu sur les hôtes Docker bloquent fréquemment le trafic Swarm. Docker gère ses propres chaînes iptables, mais les règles définies par l’utilisateur dans la chaîne `DOCKER-USER` peuvent les outrepasser. Sur un hôte Linux, exécutez : ```bash sudo iptables -L DOCKER-USER -n -v ``` Recherchez les règles `REJECT` ou `DROP` qui pourraient affecter les ports : - `2377/tcp` pour la communication de gestion du cluster - `7946/tcp` et `7946/udp` pour la communication entre nœuds - `4789/udp` pour le trafic du réseau overlay Par exemple, une règle comme celle-ci bloque le trafic VXLAN : ```text Chain DOCKER-USER (1 references) pkts bytes target prot opt in out source destination 0 0 DROP udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:4789 ``` Si une telle règle existe, supprimez-la ou ajustez-la. Vérifiez aussi que les ports sont ouverts entre les nœuds avec `ss` ou `nc` depuis l’hôte : ```bash sudo ss -lntup | grep -E '2377|7946|4789' ``` Cela montre si le démon Docker écoute sur ces ports. ### Diagnostics spécifiques aux secrets Si un service ne démarre pas à cause d’un secret manquant, inspectez les journaux du service : ```bash docker service logs ``` Un message d’erreur courant : ```text secret not found: my-secret ``` Cela signifie que le service a été créé avec une référence à un secret qui n’existe pas. Listez les secrets : ```bash docker secret ls ``` Si le secret existe mais que le conteneur ne peut pas y accéder, vérifiez la configuration des secrets du service : ```bash docker service inspect --format '{{json .Spec.TaskTemplate.ContainerSpec.Secrets}}' | jq . ``` Exemple de sortie : ```json [ { "File": { "Name": "/run/secrets/my-secret", "UID": "0", "GID": "0", "Mode": 292 }, "SecretID": "somesecretid", "SecretName": "my-secret" } ] ``` Le `File.Name` est le chemin cible. Le `Mode` est la permission octale, ici `292` en décimal qui vaut `0444` en octal, c’est-à-dire lisible par tous. Si le mode est `0`, le fichier peut être inaccessible. Vérifiez aussi que l’UID et le GID correspondent à l’utilisateur qui exécute le processus dans le conteneur. Dans le conteneur, vérifiez le fichier : ```bash ls -l /run/secrets/ ``` Si le fichier existe mais est illisible, ajustez les permissions de la cible du secret ou exécutez le conteneur en tant qu’utilisateur avec un accès approprié. ## Modes de défaillance et récupération Reconnaître les schémas de défaillance courants accélère la récupération. Pour chacun, nous décrivons le symptôme, la cause probable et les étapes concrètes de récupération. ### Échec de résolution DNS **Symptôme :** `nslookup` ou `dig` ne renvoie aucune réponse, ou le nom du service ne peut pas être résolu. **Cause :** Le service et le conteneur de test ne sont pas sur le même réseau overlay, ou le service n’a aucun réplica en cours d’exécution, ou le DNS intégré est mal configuré. **Récupération :** 1. Vérifiez les réseaux du service : ```bash docker service inspect my-service --format '{{json .Spec.TaskTemplate.Networks}}' ``` 2. Si le réseau est manquant, ajoutez-le : ```bash docker service update --network-add frontend-overlay my-service ``` 3. Assurez-vous qu’au moins un réplica est en cours d’exécution : ```bash docker service ps my-service ``` 4. Testez à nouveau la résolution depuis le conteneur de test. ### Échec de connectivité des ports **Symptôme :** `nc` signale une connexion refusée ou expire lors de la connexion au port du service. **Cause :** Le service n’écoute pas sur le port attendu à l’intérieur du conteneur, ou une règle de pare-feu bloque la connexion, ou le service n’a pas de tâches en cours d’exécution. **Récupération :** 1. Vérifiez que le service est en cours d’exécution : ```bash docker service ps my-service ``` 2. Vérifiez le port que le service pense exposer : ```bash docker service inspect my-service --format '{{json .Endpoint.Ports}}' ``` 3. Dans un conteneur en cours d’exécution du service, vérifiez les ports en écoute : ```bash docker exec netstat -tulpn | grep ``` 4. Si aucun processus n’écoute, corrigez la configuration de l’application ou la directive `EXPOSE` du Dockerfile. Si le port est en écoute mais que la connexion échoue, vérifiez les règles de pare-feu comme décrit précédemment. ### Échec d’accès au secret **Symptôme :** Le conteneur ne peut pas lire le fichier du secret, ou le fichier est manquant. **Cause :** Le secret n’est pas monté correctement, le chemin cible est incorrect ou les permissions sont trop restrictives. **Récupération :** 1. Listez les secrets et confirmez que le secret voulu existe : ```bash docker secret ls ``` 2. Recréez le service avec la bonne cible de secret si le chemin est incorrect : ```bash docker service update --secret-rm my-secret --secret-add source=my-secret,target=/run/secrets/db_password my-service ``` 3. Vérifiez dans un conteneur : ```bash docker exec ls -l /run/secrets/ ``` La sortie devrait montrer le fichier avec des permissions raisonnables, par exemple `-r--r--r-- 1 root root`. ### Dégradation des performances réseau **Symptôme :** Latence élevée ou perte de paquets entre services sur le réseau overlay. **Cause :** Mauvaise configuration du réseau overlay, problèmes de MTU ou problèmes d’infrastructure sous-jacente. **Récupération :** 1. Testez la perte de paquets : ```bash ping -c 100 ``` 2. Vérifiez les incompatibilités de MTU. Les réseaux overlay ajoutent la surcharge VXLAN, donc le MTU doit être inférieur à celui du réseau sous-jacent. Inspectez le MTU du réseau : ```bash docker network inspect frontend-overlay --format '{{json .Options}}' ``` Recherchez `com.docker.network.driver.mtu`. La valeur par défaut est généralement 1450. Si le réseau sous-jacent a un MTU de 1500 et que l’overlay est réglé sur 1500, une fragmentation peut se produire. Définissez le bon MTU lors de la création du réseau : ```bash docker network create -d overlay --opt com.docker.network.driver.mtu=1400 my-overlay ``` 3. Si les problèmes persistent, envisagez de recréer le réseau overlay et de réattacher les services. Cela perturbe le trafic, alors planifiez une fenêtre de maintenance et utilisez le plan de retour en arrière. ### Stratégies de retour en arrière Soyez toujours capable d’annuler les modifications. Pour les services, utilisez : ```bash docker service rollback ``` Cela revient à la spécification de service précédente, y compris les réseaux et les secrets. Notez que seule la spécification immédiatement précédente est stockée. Pour les changements de réseau, documentez l’état d’origine avant toute modification : ```bash docker network inspect > network-backup.json ``` Si nécessaire, supprimez le réseau et recréez-le à partir de la sauvegarde. Cependant, supprimer un réseau overlay déconnecte tous les services attachés et peut causer une brève interruption. ## Pièges courants et comment les éviter Plusieurs erreurs reviennent sur le terrain. Voici les plus fréquentes et comment les prévenir ou s’en remettre. ### 1. Tester depuis le mauvais réseau **Pourquoi cela arrive :** Il est facile de créer un conteneur de test sur le réseau bridge par défaut ou un autre overlay, puis d’essayer d’atteindre un service par son nom. La résolution DNS de Docker est limitée au réseau, donc le nom ne se résoudra pas. **Comment éviter :** Spécifiez toujours le même réseau overlay lors de la création du service de test : ```bash docker service create --name test-container --network alpine sleep 3600 ``` Vérifiez avec `docker inspect` que le conteneur de test est bien attaché au réseau voulu. ### 2. Ignorer les règles de pare-feu sur les hôtes **Pourquoi cela arrive :** Beaucoup d’administrateurs se concentrent sur le réseau des conteneurs et oublient que les pare-feu au niveau de l’hôte peuvent bloquer la communication inter-nœuds de Swarm. Les règles iptables de Docker sont généralement permissives, mais les règles ajoutées par l’utilisateur dans la chaîne `DOCKER-USER` peuvent les outrepasser. **Comment éviter :** Vérifiez toujours `iptables -L DOCKER-USER -n -v` sur les hôtes source et cible pendant le dépannage. Autorisez explicitement les ports 2377, 7946 et 4789 si vous avez une politique de pare-feu restrictive. ### 3. Négliger les chemins cibles des secrets **Pourquoi cela arrive :** Le nom du secret et le chemin du fichier dans le conteneur sont indépendants. Un développeur peut créer un secret nommé `db_password` mais configurer le service pour le monter à `/run/secrets/password`, alors que l’application attend `/run/secrets/db_password`. **Comment éviter :** Définissez une convention de nommage cohérente pour les secrets et leurs cibles. Utilisez `docker service inspect --pretty` pour confirmer le chemin cible, et testez toujours avec `cat /run/secrets/` dans un conteneur. ### 4. Supposer que la VIP est une vraie IP **Pourquoi cela arrive :** La VIP du service est une adresse IP virtuelle gérée par le maillage de routage de Docker. Elle n’est liée à aucun conteneur unique. Certains utilisateurs essaient de pinger la VIP ou de s’y connecter depuis l’extérieur de l’overlay et sont déroutés quand cela ne fonctionne que depuis l’intérieur du réseau. **Comment éviter :** Comprenez que la VIP n’est routable que depuis les conteneurs sur le même réseau overlay. Pour un accès externe, utilisez un port publié. ### 5. Ne pas vérifier le statut des réplicas du service **Pourquoi cela arrive :** Un service peut être défini mais avoir zéro réplica en cours d’exécution à cause de tâches échouées. Le DNS peut toujours résoudre le nom du service en une VIP, mais aucun conteneur backend n’existe pour gérer le trafic. **Comment éviter :** Exécutez toujours `docker service ps ` avant et pendant le dépannage. Recherchez les tâches à l’état `Running`. Si les tâches échouent, inspectez les journaux avec `docker service logs `. ## Propriété des décisions et cadence de revue Dans un contexte d’équipe, plusieurs décisions et contrôles doivent avoir un propriétaire clair et un cycle de revue régulier. | Décision ou contrôle | Rôle responsable | Fréquence de revue | |---|---|---| | Topologie réseau et conception de l’overlay | Responsable d’infrastructure (par ex., Priya Shah, responsable ingénierie) | Trimestrielle ou lors d’un changement majeur d’architecture | | Création des secrets et politique de rotation | Ingénieur sécurité (par ex., Marcus Chen, ingénieur sécurité) | Tous les 6 mois ou après toute exposition suspectée | | Rattachements réseau et expositions de ports des services | Propriétaire d’application (par ex., David Kim, responsable backend) | À chaque planification de sprint ou lors d’un changement de spécification du service | | Règles de pare-feu pour les hôtes Docker | Administrateur systèmes (par ex., Elena Rodriguez, administrateur systèmes) | Mensuelle ou après tout changement d’infrastructure | | Mise à jour du manuel de dépannage | Ingénieur DevOps (par ex., Tom Okafor, ingénieur DevOps) | Après chaque incident majeur ou trimestrielle | La fréquence peut être ajustée à la taille de votre équipe et à votre profil de risque, mais avoir une personne nommée évite le problème du « tout le monde pensait que quelqu’un d’autre le faisait ». ## Liste de contrôle des opérations Utilisez cette liste de contrôle face à un problème réseau avec les secrets Docker. Parcourez-la dans l’ordre et documentez ce que vous trouvez à chaque étape. | Étape | Action | Commande ou détails | Propriétaire | |---|---|---|---| | 1 | Vérifier les versions de Docker et de Swarm | `docker version`, `docker info` | Ingénieur d’astreinte | | 2 | Lister les nœuds et les réseaux | `docker node ls`, `docker network ls` | Ingénieur d’astreinte | | 3 | Inspecter la configuration du service | `docker service inspect --pretty ` | Propriétaire d’application | | 4 | Vérifier les montages de secrets | `docker service inspect --format '{{json .Spec.TaskTemplate.ContainerSpec.Secrets}}' \| jq .` | Ingénieur sécurité | | 5 | Créer un service de test sur le même réseau | `docker service create --name test- --network alpine sleep 3600` | Ingénieur d’astreinte | | 6 | Tester la résolution DNS | `nslookup ` dans le conteneur de test | Ingénieur d’astreinte | | 7 | Tester la connectivité des ports | `nc -zv ` dans le conteneur de test | Ingénieur d’astreinte | | 8 | Vérifier le routage | `ping`, `ip route`, `traceroute` | Ingénieur d’astreinte | | 9 | Vérifier les règles de pare-feu | `sudo iptables -L DOCKER-USER -n -v` sur les hôtes concernés | Administrateur systèmes | | 10 | Examiner les journaux du service | `docker service logs ` | Propriétaire d’application | | 11 | Tenter la récupération | Appliquer le correctif pertinent de la section Modes de défaillance | Propriétaire d’application ou astreinte | | 12 | Confirmer le plan de retour en arrière | `docker service rollback ` disponible, sauvegarde réseau enregistrée | Ingénieur d’astreinte | Après avoir résolu le problème, mettez à jour le manuel avec les nouvelles découvertes, et si un retour en arrière a été utilisé, planifiez un suivi pour mettre en œuvre un correctif permanent. ## Conclusion Le dépannage des problèmes réseau des secrets Docker n’est pas de la magie. C’est un processus méthodique d’élimination des couches. Commencez par une base de référence : confirmez les versions, la santé du Swarm et la topologie réseau. Inspectez ensuite la configuration du service, y compris les montages de secrets et les rattachements réseau. Utilisez un conteneur de test sur le même réseau overlay pour isoler les problèmes de DNS, de ports et de routage. Vérifiez les pare-feu des hôtes, car ils sont souvent négligés. Quand vous trouvez la cause profonde, appliquez un correctif ciblé et ayez toujours un plan de retour en arrière. N’oubliez pas de garder le service de test isolé de la production. Utilisez la liste de contrôle des opérations comme aide-mémoire et attribuez des propriétaires clairs pour les contrôles récurrents. Avec la pratique, vous diagnostiquerez la plupart des problèmes réseau en minutes plutôt qu’en heures, et garderez vos secrets et vos services fonctionnant sans accroc. Commencez par un pilote étroit : choisissez un service et un réseau, vérifiez la connectivité locale, puis étendez le test. Cette approche limite les risques et renforce la confiance dans le processus de dépannage.