L'indispensable débogage conteneurisé : Pourquoi Docker CLI est votre meilleur allié

Dans l'écosystème du développement web moderne, les conteneurs Docker sont devenus la norme de facto pour empaqueter, distribuer et exécuter des applications. Ils offrent une cohérence inégalée entre les environnements de développement, de staging et de production, résolvant ainsi le célèbre problème du "ça marche sur ma machine". Cependant, cette puissance s'accompagne de sa propre série de défis, notamment lorsqu'il s'agit de diagnostiquer un conteneur récalcitrant. Lorsque votre application web conteneurisée ne se comporte pas comme prévu, l'absence d'une interface graphique traditionnelle ou d'un accès direct au système d'exploitation peut dérouter même les développeurs les plus expérimentés. C'est là que la maîtrise du Docker CLI (Command Line Interface) devient non seulement utile, mais absolument essentielle. Un workflow de débogage Docker CLI structuré est la clé pour transformer ce qui pourrait être une chasse aux sorcières frustrante en un processus d'ingénierie logicielle robuste et efficace. Chez Voronkin Studio, nous savons que le temps, c'est de l'argent, et qu'un conteneur en panne peut paralyser un projet. Cet article a pour but de vous guider à travers une méthodologie systématique, en utilisant les outils natifs de Docker, pour diagnostiquer rapidement et précisément les problèmes au sein de vos conteneurs. Nous allons explorer comment les codes de sortie, les journaux et les informations structurées peuvent être exploités pour obtenir une vision claire de ce qui se passe sous le capot, vous permettant ainsi de résoudre les problèmes avec confiance et rapidité. Adopter cette approche, c'est garantir la robustesse de vos déploiements et la sérénité de vos équipes.

Les fondamentaux du diagnostic : Statut, Logs et Inspection

Avant de plonger dans les arcanes des problèmes complexes, il est crucial de maîtriser les commandes Docker CLI de base qui constituent la première ligne de défense de tout développeur. Ces commandes vous fournissent un aperçu immédiat de l'état de vos conteneurs et sont le point de départ de tout processus de débogage. La première étape consiste toujours à vérifier l'état de vos conteneurs. La commande `docker ps` est votre alliée la plus fidèle. Elle liste tous les conteneurs *en cours d'exécution*. docker ps Si votre conteneur n'apparaît pas dans cette liste, c'est un signe immédiat qu'il a soit échoué au démarrage, soit s'est arrêté prématurément. Pour voir tous les conteneurs, y compris ceux qui se sont arrêtés, utilisez l'option `-a` : docker ps -a Cette commande est cruciale car elle révèle non seulement les conteneurs arrêtés, mais aussi leur `STATUS` (par exemple, "Exited (1) 2 minutes ago") et, de manière critique, leur `EXIT CODE`. Le code de sortie est souvent le premier indice puissant sur la nature du problème. Un code de sortie de `0` indique généralement une sortie normale et réussie (bien que pour un serveur web, cela puisse signifier qu'il s'est arrêté volontairement, ce qui est souvent une erreur). Tout autre code (par exemple, `1`, `137`, `127`) signale une anomalie ou une erreur. Une fois que vous avez identifié un conteneur problématique (par son `CONTAINER ID` ou son `NAMES`), la prochaine étape naturelle est de consulter ses journaux. Les journaux sont la voix de votre application. La commande `docker logs` permet de récupérer les sorties `stdout` et `stderr` d'un conteneur. docker logs [CONTAINER_ID_OR_NAME] Pour les applications web, cela inclut souvent les messages d'erreur de votre serveur web (Nginx, Apache), les erreurs d'exécution de votre runtime (Node.js, PHP-FPM, Python Gunicorn), les problèmes de connexion à la base de données, ou les messages de votre application elle-même. Nous détaillerons l'utilisation avancée de `docker logs` plus tard, mais pour l'instant, sachez que c'est là que vous trouverez le récit direct des événements qui ont mené à l'échec. Enfin, pour obtenir une vue d'ensemble détaillée de la configuration d'un conteneur, `docker inspect` est inestimable. Cette commande renvoie un document JSON massif contenant toutes les informations imaginables sur un conteneur : son état, ses volumes montés, ses ports exposés, ses variables d'environnement, ses configurations réseau, et bien plus encore. docker inspect [CONTAINER_ID_OR_NAME] Bien que son output puisse sembler intimidant au premier abord, il est extrêmement utile pour vérifier si les configurations attendues (par exemple, les variables d'environnement pour la connexion à la base de données, les chemins de fichiers montés) sont bien celles qui sont appliquées au conteneur. C'est souvent là que l'on découvre des erreurs de configuration subtiles qui ne sont pas immédiatement apparentes dans les logs. En maîtrisant ces trois commandes – `docker ps`, `docker logs`, et `docker inspect` – vous disposerez d'une base solide pour entamer tout processus de débogage Docker. Elles vous permettent de passer d'une simple observation d'un problème à une compréhension concrète de l'état et de la configuration du conteneur, ouvrant la voie à une résolution efficace.

Décrypter les codes de sortie : Le premier indice d'un conteneur en détresse

Lorsque vous examinez la liste des conteneurs arrêtés avec `docker ps -a`, l'information la plus immédiate et souvent la plus révélatrice est le "Exit Code" (code de sortie). Ce petit nombre est bien plus qu'une simple formalité ; il est le verdict final du processus principal qui s'exécutait à l'intérieur de votre conteneur. Comprendre la signification de ces codes est fondamental pour un diagnostic rapide et précis. Un code de sortie de `0` indique, par convention, que le programme s'est terminé avec succès. Pour un script ponctuel, c'est généralement ce que l'on attend. Cependant, pour un conteneur hébergeant un service web (comme Nginx, un serveur Node.js, PHP-FPM, ou une base de données), un code de sortie `0` est souvent un signe de problème. Pourquoi ? Parce que ces services sont conçus pour fonctionner en continu. Si un tel conteneur se termine avec un code `0`, cela signifie généralement que le processus principal a été arrêté volontairement, peut-être parce qu'il n'a pas pu démarrer correctement, qu'il a reçu un signal d'arrêt, ou qu'il a exécuté une tâche unique et s'est ensuite arrêté. Dans ce cas, il faut investiguer pourquoi le service n'est pas resté en vie. Les codes de sortie non nuls signalent une erreur ou une condition anormale. Bien qu'il n'y ait pas de norme universelle stricte pour tous les codes non nuls au-delà de `0`, certains sont couramment rencontrés et ont des significations implicites fortes : * Code 1 : Erreur générique / Erreur non spécifiée. C'est l'un des codes de sortie les plus frustrants car il est très générique. Il indique qu'un problème est survenu, mais le programme n'a pas fourni de détail plus spécifique. C'est le moment de plonger dans les logs (avec `docker logs`) pour trouver la cause racine. Cela peut être n'importe quoi, d'une erreur de syntaxe dans un script à une exception non gérée dans le code de l'application. * Code 126 : Permission Denied. Ce code signifie que le programme ou le script que vous avez tenté d'exécuter n'a pas les permissions d'exécution nécessaires. Vérifiez les droits sur le fichier d'entrée de votre conteneur (par exemple, le script `start.sh` ou l'exécutable de l'application) ou sur les fichiers qu'il tente d'accéder. * Code 127 : Command Not Found. C'est un grand classique. Le processus principal spécifié dans votre `Dockerfile` ou via la commande `docker run` n'a pas été trouvé dans le `PATH` du conteneur. Cela peut être dû à une faute de frappe dans le nom de la commande, ou à l'oubli d'installer le programme requis dans l'image Docker. Par exemple, si vous essayez d'exécuter `npm start` mais que `npm` n'est pas installé ou n'est pas dans le PATH. * Codes 137, 139, etc. : Problèmes de signaux. Ces codes sont dérivés de la valeur du signal qui a terminé le processus, plus 128. * Code 137 (128 + 9) : SIGKILL. C'est un signal d'arrêt forcé. Le conteneur a été tué de force. Dans le contexte de Docker, cela signifie très souvent que le conteneur a manqué de mémoire. Le système d'exploitation hôte (ou Docker lui-même, si des limites de mémoire sont configurées) a dû tuer le processus pour libérer des ressources. C'est une indication forte de problèmes de ressources. * Code 139 (128 + 11) : SIGSEGV (Segmentation Fault). Indique généralement une tentative d'accès à une zone de mémoire non allouée ou protégée. C'est souvent le signe d'un bug grave dans le code de l'application (par exemple, un dépassement de tampon, un pointeur nul déréférencé dans des langages comme C/C++ ou des extensions natives). Lorsqu'un conteneur s'arrête avec un code de sortie non nul, la première chose à faire est de rechercher ce code spécifique et de consulter les logs immédiatement. Le code de sortie vous donne une direction générale, mais les logs vous donneront les détails granulaires nécessaires pour comprendre pourquoi ce code a été émis. Par exemple, un `Exit Code 1` avec des logs indiquant "Error: Cannot find module 'express'" vous orientera vers un problème de dépendances Node.js manquantes. En somme, les codes de sortie sont les titres des chapitres de l'histoire de l'échec de votre conteneur. Apprenez à les lire, et vous aurez une longueur d'avance dans votre processus de débogage.

Plongée dans les journaux : Maîtriser `docker logs` pour une visibilité accrue

Après avoir identifié un conteneur problématique et potentiellement décrypté son code de sortie, la prochaine étape logique, et souvent la plus riche en informations, est d'examiner ses journaux. Les logs sont le journal de bord de votre application, enregistrant les événements, les avertissements et surtout les erreurs qui se produisent à l'intérieur du conteneur. Maîtriser `docker logs` est donc fondamental pour tout développeur web travaillant avec Docker. La commande de base `docker logs [CONTAINER_ID_OR_NAME]` est un bon point de départ, mais elle peut rapidement devenir insuffisante pour des applications générant un volume important de logs. Heureusement, Docker CLI offre plusieurs options pour rendre l'analyse des logs plus efficace : * Suivre les logs en temps réel (`-f` ou `--follow`) : Pour les conteneurs en cours d'exécution ou qui redémarrent en boucle, il est souvent utile de voir les logs au fur et et à mesure qu'ils sont générés. docker logs -f [CONTAINER_ID_OR_NAME] Ceci est particulièrement pratique pour observer le processus de démarrage d'un service web ou pour voir les erreurs se produire en direct lors d'une interaction avec l'application. * Afficher les dernières lignes (`--tail`) : Si les logs sont très volumineux et que vous êtes principalement intéressé par les événements les plus récents, l'option `--tail` est votre amie. docker logs --tail 100 [CONTAINER_ID_OR_NAME] Ceci affichera les 100 dernières lignes des logs, ce qui est souvent suffisant pour capturer les messages d'erreur les plus récents sans avoir à scruter un fichier entier. * Inclure les timestamps (`-t` ou `--timestamps`) : Pour comprendre la séquence temporelle des événements, surtout dans un environnement distribué ou avec plusieurs services interagissant, les horodatages sont cruciaux. docker logs -t [CONTAINER_ID_OR_NAME] Cela ajoute un horodatage ISO8601 à chaque ligne de log, facilitant la corrélation des événements entre différents conteneurs ou services. * Filtrer les logs par période (`--since` et `--until`) : Si vous savez que le problème s'est produit à un moment précis, vous pouvez filtrer les logs pour ne voir que ceux générés dans un intervalle de temps donné. docker logs --since "2023-10-26T10:00:00" --until "2023-10-26T10:30:00" [CONTAINER_ID_OR_NAME] Ou plus simplement : docker logs --since 5m [CONTAINER_ID_OR_NAME] (pour les logs des 5 dernières minutes) Ces options sont particulièrement utiles pour isoler les logs pertinents sans être submergé par des gigaoctets de données. * Afficher les logs des services multiples (`docker-compose logs`) : Lorsque vous travaillez avec des applications multi-conteneurs gérées par Docker Compose, la commande `docker-compose logs` est encore plus puissante. Elle agrège les logs de tous les services définis dans votre `docker-compose.yml`. docker-compose logs -f Vous pouvez également filtrer par service spécifique : docker-compose logs -f webapp Pour les développeurs web, les logs contiendront une mine d'informations : * Erreurs de configuration de serveur web : Par exemple, Nginx affichera des erreurs de configuration de vhost, des problèmes de chemins de fichiers. * Erreurs d'exécution d'application : Exceptions non gérées dans votre code Node.js, PHP, Python, Java. Messages "Cannot connect to database", "File not found", etc. * Problèmes de dépendances : Messages indiquant des modules manquants ou des versions incompatibles. * Problèmes de permissions : Bien que parfois indiqués par des codes de sortie, les logs peuvent donner le chemin exact du fichier ou répertoire inaccessible. * Avertissements de performance : Des messages de votre runtime ou framework signalant des requêtes lentes ou des surcharges mémoire. Une bonne pratique est de s'assurer que votre application conteneurisée logue ses informations importantes vers `stdout` et `stderr`. C'est la manière idiomatique de gérer les logs dans Docker, permettant au moteur Docker de les collecter et de les rendre accessibles via `docker logs`. Évitez de logger directement vers des fichiers à l'intérieur du conteneur, car ces logs peuvent être perdus si le conteneur est supprimé, et ils sont plus difficiles à centraliser. En somme, les logs sont la narration détaillée des événements. Apprenez à les lire, à les filtrer et à les interpréter, et vous tiendrez entre vos mains la clé de la résolution de la plupart des problèmes conteneurisés.

L'anatomie d'un conteneur : Utiliser `docker inspect` pour des insights cruciaux

Après avoir consulté les codes de sortie et les journaux, il arrive que le problème persiste ou que les informations obtenues soient ambiguës. C'est à ce moment que `docker inspect` entre en jeu, offrant une vue radiographique complète de l'état et de la configuration d'un conteneur. Cette commande est un outil de diagnostic puissant car elle révèle des détails que les logs ne peuvent pas toujours fournir, notamment tout ce qui concerne l'environnement d'exécution du conteneur. La commande `docker inspect [CONTAINER_ID_OR_NAME]` renvoie une structure JSON détaillée. Bien que l'output puisse être dense, sa richesse est inestimable pour les débogueurs méticuleux. Voici les sections clés à examiner : * `State` : Cette section fournit un aperçu de l'état actuel du conteneur. Vous y trouverez des informations comme `Running` (est-il en cours d'exécution ?), `Pid` (le PID du processus principal à l'intérieur du conteneur), `ExitCode` (reconfirmant le code de sortie), `StartedAt` et `FinishedAt` (les horodatages de démarrage et d'arrêt), et `Error` (un message d'erreur si le conteneur n'a pas pu démarrer). C'est une excellente façon de vérifier si le conteneur a vraiment démarré et quand il s'est arrêté. * `Config` : Cette section reflète la configuration de l'image à partir de laquelle le conteneur a été créé. Elle inclut `Hostname`, `Image` (l'image Docker utilisée), `WorkingDir` (le répertoire de travail par défaut), `Entrypoint` et `Cmd` (les commandes exécutées au démarrage du conteneur), et `Env` (les variables d'environnement définies dans l'image ou passées au démarrage). Il est fréquent de trouver des erreurs ici, comme une variable d'environnement mal orthographiée ou manquante, ce qui peut empêcher une application web de se connecter à sa base de données ou de charger des configurations spécifiques. * `HostConfig` : Cette section contient les options spécifiques à l'hôte passées lors de la création du conteneur. C'est ici que vous vérifierez les `PortBindings` (les mappages de ports entre l'hôte et le conteneur), `Binds` (les montages de volumes), `Memory` et `CpuShares` (les limites de ressources), et `RestartPolicy` (la politique de redémarrage du conteneur). Des problèmes de mappage de ports (par exemple, le port de l'application exposé sur le mauvais port hôte ou un port déjà occupé) ou des volumes mal montés sont des causes fréquentes de dysfonctionnement pour les applications web. * `NetworkSettings` : Cruciale pour déboguer les problèmes de connectivité. Cette section détaille les configurations réseau du conteneur, y compris son `IPAddress`, la `Gateway`, et les `Ports` exposés. Si votre application web ne peut pas communiquer avec d'autres services (comme une base de données dans un autre conteneur ou un service externe), cette section vous aidera à vérifier l'adresse IP du conteneur, son réseau, et si les ports nécessaires sont bien ouverts et accessibles. Les `PortBindings` sous `NetworkSettings.Ports` sont particulièrement importants pour s'assurer que le port interne de votre application est correctement publié sur l'hôte. * `Mounts` : Cette sous-section de `HostConfig` ou parfois une section de premier niveau peut montrer les volumes montés sur le conteneur. Elle indique la `Source` (le chemin sur l'hôte) et la `Destination` (le chemin à l'intérieur du conteneur). Des erreurs de chemin, des permissions incorrectes sur le volume hôte, ou un volume non monté du tout peuvent empêcher une application de lire ses fichiers de configuration, de charger des assets, ou de persister des données. Pour naviguer dans cette sortie JSON massive, des outils comme `jq` sont inestimables. Par exemple, pour extraire spécifiquement les variables d'environnement d'un conteneur : docker inspect [CONTAINER_ID_OR_NAME] | jq '.[0].Config.Env' Ou pour vérifier les mappages de ports : docker inspect [CONTAINER_ID_OR_NAME] | jq '.[0].NetworkSettings.Ports' En utilisant `docker inspect`, vous pouvez valider que le conteneur a été lancé avec la configuration attendue, confirmant si les variables d'environnement sont correctes, si les volumes sont bien montés, si les ports sont correctement exposés et si les limites de ressources sont appropriées. Il est souvent le dernier recours lorsque les logs ne donnent pas de réponse claire et que l'on soupçonne un problème d'environnement ou de configuration plutôt qu'un bug applicatif pur. C'est un outil qui transforme les suppositions en certitudes.

Interaction en temps réel : `docker exec` pour une intervention chirurgicale

Une fois que vous avez identifié un problème grâce aux codes de sortie, aux logs et à l'inspection de la configuration, il est souvent nécessaire d'interagir directement avec le conteneur en cours d'exécution pour approfondir le diagnostic ou appliquer une correction temporaire. C'est là que la commande `docker exec` devient un outil indispensable dans l'arsenal du développeur. Elle vous permet d'exécuter des commandes à l'intérieur d'un conteneur en vie, sans avoir à le redémarrer ou à le reconstruire. La syntaxe de base de `docker exec` est la suivante : docker exec [OPTIONS] [CONTAINER_ID_OR_NAME] [COMMAND] [ARG...] L'utilisation la plus courante et la plus puissante de `docker exec` est d'obtenir un shell interactif à l'intérieur du conteneur. Cela vous permet de naviguer dans le système de fichiers du conteneur, d'exécuter des utilitaires de diagnostic, d'inspecter des fichiers de configuration, ou même de modifier temporairement des fichiers pour tester une hypothèse. docker exec -it [CONTAINER_ID_OR_NAME] bash (ou `sh` si `bash` n'est pas disponible dans l'image, ce qui est courant pour les images minimalistes) Les options `-i` (interactive) et `-t` (tty) sont cruciales pour avoir une session de shell fonctionnelle. Sans elles, la commande s'exécuterait en arrière-plan et vous ne verriez pas d'invite de commande. Voici quelques scénarios où `docker exec` est particulièrement utile pour les développeurs web : * Vérification des chemins de fichiers et des permissions : Si vos logs indiquent un problème de fichier introuvable ou de permission refusée, vous pouvez utiliser `docker exec` pour naviguer vers le répertoire en question et vérifier l'existence du fichier (`ls`), ses permissions (`ls -l`), ou même son contenu (`cat`). docker exec -it webapp ls -l /app/config.php docker exec -it webapp cat /app/logs/error.log * Test de connectivité réseau : Si votre application ne peut pas se connecter à une base de données ou à un autre service, vous pouvez exécuter des commandes comme `ping`, `telnet` (si installé), ou `curl` à l'intérieur du conteneur pour tester la connectivité depuis la perspective de l'application. docker exec -it webapp ping database_host docker exec -it webapp curl http://another-service:8080/health * Inspection des variables d'environnement en direct : Bien que `docker inspect` montre les variables d'environnement au démarrage, il peut être utile de voir l'environnement tel qu'il est perçu par le shell du conteneur. docker exec -it webapp env * Exécution d'outils de diagnostic spécifiques à l'application : Si votre application ou runtime dispose de ses propres outils de débogage (par exemple, `npm doctor` pour Node.js, `php -v` pour PHP, `ps aux` pour voir les processus en cours), `docker exec` vous permet de les exécuter. docker exec -it webapp npm doctor docker exec -it webapp ps aux * Accès à une base de données : Si vous avez un conteneur de base de données (par exemple, PostgreSQL ou MySQL) et que vous soupçonnez un problème de données ou de schéma, vous pouvez vous connecter directement à la base de données depuis l'intérieur de son conteneur. docker exec -it database_container psql -U user_name db_name * Redémarrage de services internes (avec prudence) : Dans certains cas, vous pourriez vouloir redémarrer un service spécifique à l'intérieur du conteneur sans redémarrer le conteneur entier. Cependant, cela est généralement déconseillé car cela va à l'encontre du principe d'immutabilité des conteneurs. Il est préférable de redémarrer le conteneur entier ou de reconstruire l'image. Un point important à noter est que les modifications effectuées via `docker exec` ne sont pas persistantes. Si vous modifiez un fichier à l'intérieur du conteneur, ces changements seront perdus si le conteneur est supprimé ou recréé. `docker exec` est un outil de diagnostic et de test ponctuel, pas une méthode pour patcher les conteneurs en production. Une fois que vous avez identifié la cause du problème, la solution correcte est généralement de modifier votre `Dockerfile`, votre `docker-compose.yml`, ou votre code source, puis de reconstruire et de redéployer le conteneur. En résumé, `docker exec` est votre scalpel pour des interventions chirurgicales. Il vous permet de tester des hypothèses, de vérifier des états en direct et d'obtenir des informations détaillées qui ne sont pas toujours visibles de l'extérieur, complétant ainsi les informations obtenues par les logs et l'inspection.

Un workflow de débogage Docker CLI structuré pour développeurs web

Pour transformer les commandes individuelles en un processus de débogage efficace, il est essentiel d'adopter un workflow structuré. Cette approche systématique vous permettra d'attaquer les problèmes de conteneurs avec logique et méthode, réduisant le temps d'arrêt et la frustration. Voici un workflow pas à pas, optimisé pour les développeurs web :

Étape 1 : Observation Initiale et Vérification du Statut

Dès qu'un problème est signalé (application inaccessible, erreur 500, etc.), la première action est de vérifier l'état des conteneurs. docker ps -a Recherchez le conteneur de votre application web (par exemple, votre frontend, backend API) et tout service essentiel (base de données, cache).

  • Si le conteneur est "Exited" : Notez attentivement le code de sortie. C'est votre premier indice crucial.
  • Si le conteneur est "Up" mais l'application ne fonctionne pas : Cela suggère un problème interne à l'application ou une mauvaise configuration réseau/port.
  • Si le conteneur est en boucle de redémarrage : C'est une indication claire d'un problème de démarrage critique.

Étape 2 : Analyse des Logs pour les Erreurs et Avertissements

Le journal est votre meilleure source d'information détaillée. docker logs -f --tail 100 [CONTAINER_ID_OR_NAME] Surveillez le démarrage du conteneur. Cherchez des messages d'erreur (`ERROR`, `FATAL`), des avertissements (`WARN`), des traces de pile (stack traces), ou des messages indiquant des problèmes de connexion à d'autres services (base de données, API externes).

  • Exemple : Si le conteneur s'est arrêté avec `Exit Code 1`, les logs révéleront très probablement la raison exacte (ex: "Error: Missing configuration file", "Database connection refused").
  • Si le conteneur est "Up" mais l'application ne répond pas : Les logs peuvent montrer que le serveur web n'a pas pu lier un port, que l'application n'a pas pu démarrer son processus principal, ou qu'elle rencontre des erreurs lors des requêtes entrantes.

Étape 3 : Inspection Approfondie de la Configuration

Si les logs ne sont pas clairs ou si le problème semble lié à l'environnement ou à la configuration, `docker inspect` est la prochaine étape. docker inspect [CONTAINER_ID_OR_NAME] | less (ou `| jq '.'` si `jq` est installé pour une meilleure lisibilité) Concentrez-vous sur :

  • `Config.Env` : Les variables d'environnement sont-elles toutes présentes et correctes ? (par exemple, `DATABASE_URL`, `API_KEY`).
  • `HostConfig.PortBindings` : Les ports sont-ils correctement mappés entre l'hôte et le conteneur ?
  • `HostConfig.Binds` / `Mounts` : Les volumes sont-ils montés aux bons endroits et avec les bonnes permissions ?
  • `NetworkSettings.IPAddress` : Le conteneur a-t-il une adresse IP et est-il sur le bon réseau ?
  • `Config.Entrypoint` et `Config.Cmd` : La commande de démarrage est-elle celle attendue ?

Des erreurs subtiles de configuration sont souvent découvertes ici, comme un chemin de fichier incorrect dans un volume, une variable d'environnement mal typée, ou un port déjà occupé sur l'hôte.

Étape 4 : Diagnostic Interactif avec `docker exec`

Lorsque vous avez une hypoth