Docker ( 4 articles - Voir la liste )

Astuce Utiliser le débogage pas à pas avec Docker et PHPStorm

Docker simplifie beaucoup de problématiques d’environnement pour les développeurs.
Quand la configuration de Docker est correcte, un développeur peut lancer un projet rapidement sans avoir à installer la bonne version de PHP, de la base de données, etc.

Malheureusement, cela complexifie aussi la communication entre ce qui tourne sur votre système hôte (ex : Windows) et les services nécessaires au projet (typiquement : PHP).

Voici comment configurer PHPStorm pour utiliser le débogage pas à pas d’XDebug, quand PHP est dockerisé.

Prérequis

PHP avec xDebug

Avant de parler de débogage pas à pas, il faut déjà qu’XDebug soit installé dans votre image docker. Voici un exemple d’image Docker avec PHP 8.4 et XDebug :

FROM php:8.4-fpm-alpine3.20

# Paramétrage du chemin vers les sources dans le conteneur
ENV MOUNT_DIR /srv/php
RUN mkdir -p ${MOUNT_DIR}
WORKDIR ${MOUNT_DIR}

# Installation d’XDebug
RUN install-php-extensions xdebug
COPY config/xdebug.ini $PHP_INI_DIR/conf.d/

Elle utilise ce fichier de config xdebug.ini (dans le répertoire config/) qui sera injecté dans l’image :

;config/xdebug.ini
xdebug.mode = debug,develop,profile
xdebug.start_with_request = trigger
xdebug.client_host = host.docker.internal

On peut builder l’image en local avec une commande du type :

docker build . -t my-group/my-image

Débogage pas à pas

Objectif

Dans l’exemple qui suit, on supposera qu’on souhaite déboguer le fichier src/Controller/TestController.php, lorsqu’on accède à la page http://localhost:8000/test.

Fichier PHP à déboguer

L’exemple utilise Symfony, mais c’est la même chose pour un autre contexte PHP. C’est bien un fichier index.php qui est exécuté ici, et il se charge ensuite d’appeler la méthode number() du fichier TestController.php.

Notez le point rouge dans la marge à gauche (l. 18). Il représente un point d’arrêt : là où vous souhaitez arrêter l’exécution pour déboguer. Pour ajouter un point d’arrêt, cliquez dans la marge à gauche de la ligne de code juste avant laquelle vous souhaitez arrêter l’exécution pour déboguer.
Ici, l’exécution s’arrêtera donc juste avant d’exécuter la ligne 18.

Configuration

Dans PHPStorm, on peut activer le débogage pas à pas en cliquant sur le bouton « téléphone rouge », qui devient vert quand il est activé (aussi disponible en bas du menu Run : Start Listening for PHP Debug Connections).

Boutons de débogage

Mais avant, il faut cliquer sur la liste déroulante Current file à côté, puis sur Edit Configurations....

Nouvelle configuration de Run

Dans la fenêtre de configuration :

  • Cliquez sur le bouton Add
  • Sélectionnez PHP Remote debug
  • Nommez la configuration (ex : Docker)

Boutons de débogage

  • Cliquez sur le lien Validate
  • Sélectionnez le bouton radio Output phpinfo()
  • Créez un fichier php contenant uniquement phpinfo();
  • Affichez-le dans votre navigateur et copiez la source de la page (via Ctrl+U)
  • Collez le code HTML dans le champ texte de la fenêtre de configuration
  • Cliquez sur le bouton Validate.
    PHPStorm va valider une série d’éléments et indiquer si XDebug est bien opérationnel :

Validation de la présence d’XDebug

  • Cliquez sur le bouton Cancel.

Extension de navigateur

Pour simplifier le débogage, vous pouvez installer une extension de navigateur, qui ajoutera une variable dans le header des requêtes, pour indiquer au serveur qu’on souhaite utiliser le débogage pas à pas.

Il en existe plusieurs, comme Xdebug Helper.

Elles fonctionnent toutes plus ou moins de la même manière, en ajoutant un bouton pour activer/désactiver le débogage :

Bouton de l’extension de navigateur

Débogage

  • Cliquez sur le bouton « téléphone rouge » dans PHPStorm pour activer le débogage
  • Cliquez sur le bouton « insecte » (ajouté par l’extension) dans votre navigateur pour activer le débogage
  • Appelez votre page à déboguer.
    La page devrait rester bloquée en cours de chargement, et PHPStorm devrait afficher une fenêtre indiquant qu’il a capté un script à déboguer :

Débogage entrant

  • Cliquez sur le bouton Accept

Normalement, rien ne se passe et la page s’affiche normalement. PHPStorm affiche un message d’alerte, car il n’a pas réussi à faire le lien entre la requête et le fichier PHP concret à déboguer :

Message d’alerte

  • Cliquez sur le lien PHP|Servers dans le message (ou recherchez cette configuration depuis la fenêtre de Settings globale de PHPStorm)
  • Créez un nouveau server (ex : nommé localhost).
  • Par défaut, seulement le répertoire contenant le fichier index.php est mappé. Il faut ajouter le répertoire racine de votre application PHP.
    Dans le tableau, la colonne de gauche indique le chemin physique de votre application sur votre machine ( probablement un répertoire WSL si vous êtes sous Windows). Celle de droite indique le chemin de l’application à l’intérieur de votre conteneur docker (/srv/php correspond au chemin indiqué dans le Dockerfile précédent).

Paramétrage du mapping des fichiers

Normalement, tout est opérationnel. Vous pouvez recharger votre page de test et l’exécution devrait s’arrêter au niveau de votre point d’arrêt.

Dans la section basse de votre IDE, apparait la variable locale $randomNumbers, avec sa valeur courante :

Débogage de la variable $randomNumbers

Erreur Docker – unauthorized: HTTP Basic: Access denied

Gitlab semble privilégier l’authentification via jeton d’accès personnel, pour se connecter au registre de conteneurs docker.

Remarque : Dans cet article, on considère que l’instance Gitlab hébergeant le registre de conteneurs avec lequel vous souhaitez interagir a pour URL https://my-gitlab.com. Remplacez-la par la vôtre, sans oublier d’y ajouter le port, si besoin.

Si vous n'êtes pas authentifié via un jeton, vous obtenez l’erreur suivante à chaque git pull ou git push :

# Utilisez l’URL de votre instance gitlab privée ou celle de gitlab.com
> docker pull my-gitlab.com/my-project-group/my-project/my/image:latest
Error response from daemon: Head "https://my-gitlab.com/my-project-group/my-project/my/image/manifests/latest": 
unauthorized: HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled 
and you must use a personal access token instead of a password. 
See https://my-gitlab.com/help/user/profile/account/two_factor_authentication#troubleshooting

Génération d’un jeton d’accès personnel

Pour éviter cela, il vous faut générer un nouveau jeton d’accès dans Gitlab :

  • Accédez à la page Personal access tokens de gitlab (https://my-gitlab.com/-/user_settings/personal_access_tokens)
  • Cliquez sur le bouton « Ajouter un nouveau jeton »
  • Précisez un nom de jeton (évitez les guillemets " et antislash \)
  • Définissez éventuellement la date d’expiration du jeton
  • Cochez les cases read_api, read_registry (et éventuellement write_registry si vous comptez faire des docker push)
  • Sauvegardez le jeton généré dans un espace sécurisé

Authentification avec le jeton

Authentifiez-vous auprès de votre instance Gitlab, en ligne de commande :

docker login my-gitlab.com --username "My token name" --password "glpat-as767nCwxmEfDhf_yHA7"

Cette commande revient à celle de login classique de docker, avec :

  • pour nom d’utilisateur, le nom du jeton tel qu’affiché dans le tableau listant les jetons
  • pour mot de passe, le jeton sauvegardé

Remarque :
Comme docker l’indique en message d’alerte au lancement de la commande, celle-ci n’est pas sécurisée. En effet, votre mot de passe sera stocké dans l’historique bash des commandes lancées.

Pour éviter cela, stockez plutôt le jeton dans un fichier :

# Créez un fichier ~/my_token.txt contenant votre jeton d’accès
cat ~/my_token.txt | docker login my-gitlab.com --username "My token name" --password-stdin
rm ~/my_token.txt

ou en variable d’environnement :

echo "$MY_TOKEN" | docker login my-gitlab.com --username "My token name" --password-stdin

Erreur Docker écrase le réseau VPN

Lorsque docker crée des réseaux virtuels entre ses conteneurs, il utilise des plages IP.
En général pas de problème, il utilise des plages non couramment utilisées.

Par contre, si ses plages habituelles ne sont pas disponibles (ou pour d'autres raisons ?), il est possible qu'il en utilise une autre, par exemple 192.168.x.x.
Cela peut alors être problématique, surtout si vous utilisez un VPN ou des ressources réseaux en parallèle, car cette plage est classiquement utilisée. On peut alors avoir un conflit d'adressage et les ressources réseaux ou du VPN peuvent ne plus être accessibles.

Pour corriger ça, une première approche consiste à killer le réseau (créé par docker) qui pose problème puis à le recréer.
Pour cela :

# Listage des réseaux créés par docker
docker network list

# Identifiez le réseau correspondant au conteneur qui a causé le problème (copiez son ID)
# Pour vérifier la plage IP qu'il utilise :
docker network inspect <ID>

# Suppression du réseau qui pose problème
docker network rm <ID>

Si cela ne suffit pas, essayez la suite de la procédure proposée ici.

Astuce Supprimer les images/conteneurs/volumes docker

Pour supprimer tous les conteneurs docker :

docker rm $(docker ps -a -q)

Pour supprimer toutes les images docker :

docker rmi $(docker images -q)

Pour supprimer tous les volumes docker :

docker volume prune