Dieser Artikel bildet den vorläufigen Abschluss meiner kleinen Artikel-Serie über Docker. Bisher habe ich die Installation unter Ubuntu 15.04, die Datenverwaltung in Docker Volumes und die Kommunikation mit Docker Containern betrachtet. Zum Abschluss geht es um Remote Debugging im Docker Container mit Xdebug.
Xdebug ist eine Erweiterung für PHP die sich in die Verarbeitung der Skripte einhängt. Mit ihr ist es unter anderem möglich, schrittweise durch PHP-Programme zu gehen und dabei die Zustände der Variablen zu begutachten. Ich gehe an dieser Stelle nur auf das Remote Debugging Feature ein. Wer sich für die Stack Traces, das Profiling oder weitere Funktionen interessiert findet dazu auf der offiziellen Seite einiges an Dokumentation.
Server einrichten
Im ersten Schritt muss Xdebug im Container installiert werden. Ich verwende für dieses Beispiel wieder das phpmysqli-Image aus meinem vorherigen Artikel und habe das Dockerfile etwas erweitert.
FROM php:apache RUN docker-php-ext-install mysqli mbstring # zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so RUN pecl install xdebug RUN echo 'zend_extension = /usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so' >> /usr/local/etc/php/php.ini RUN touch /usr/local/etc/php/conf.d/xdebug.ini; \ echo xdebug.remote_enable=1 >> /usr/local/etc/php/conf.d/xdebug.ini; \ echo xdebug.remote_autostart=0 >> /usr/local/etc/php/conf.d/xdebug.ini; \ echo xdebug.remote_connect_back=1 >> /usr/local/etc/php/conf.d/xdebug.ini; \ echo xdebug.remote_port=9000 >> /usr/local/etc/php/conf.d/xdebug.ini; \ echo xdebug.remote_log=/tmp/php5-xdebug.log >> /usr/local/etc/php/conf.d/xdebug.ini;
Ich beginne wieder mit dem offiziellen php:apache-Image aus dem Docker Hub und installiere zuerst die Unterstützung für mysqli und mbstring. Mit PECL wird dann Xdebug (aktuell in Version 2.3.2) installiert und „manuell“ in php.ini eingetragen. Die letzten Zeilen erzeugen eine Datei namens xdebug.ini in /usr/local/etc/php/conf.d/ und setzen ein paar Variablen: Remote Debugging aktivieren, kein Autostart, Port 9000 und Logging in /tmp; soweit ist alles klar. Wirklich interessant ist xdebug.remote_connect_back=1 . Hiermit weise ich Xdebug an, sich mit der Maschine zu verbinden, von welcher der zu debuggende Aufruf kam. Normalerweise würde man eher xdebug.remote_host definieren und dort fest die IP-Adresse eintragen, die zum Remote Debugging berechtigt ist, aber dann müsste man das Dockerfile immer an die eigene Umgebung anpassen.
Hinweis: Wenn man den Container anders als in meinen bisherigen Beispielen nicht mit docker run –rm –name web … phpmysqli sondern ohne den Parameter ‚rm‘ gestartet hat, wird sich Docker an dieser Stelle darüber beschweren, dass es einen Container mit dem Namen ‚web‘ bereits gibt. docker ps -a listet alle existierenden Container auf und docker rm web entfernt ihn. Auch das Docker Image ‚phpmysqli‘ ist vielleicht schon vorhanden. Mit docker images werden die lokal vorhandenen Images aufgelistet und mit docker rmi phpmysqli wird das alte Image gelöscht.
Anschließend kann ich den ‚web‘-Container wieder starten. Ob alles geklappt hat lässt sich über php -i oder phpinfo() in Erfahrung bringen:
> docker exec -ti web bash root@a92a653e7a5b:/var/www/html# php -i phpinfo() PHP Version => 5.6.9 ... weit unten ... xdebug xdebug support => enabled Version => 2.3.2
Netter Weise gibt es mit dem Xdebug Wizard ein bisschen Hilfe beim Einrichten, wenn es nicht gleich richtig funktioniert. Dort kann man einfach die komplette Ausgabe von php -i in ein Feld kopieren und bekommt die relevanten Informationen sowie ein paar Tipps angezeigt.
Client einrichten
Als nächstes muss der Client – hier am Beispiel von IntelliJ IDEA – eingerichtet werden. Genau genommen ist beim Remote Debugging im Übrigen die Rolle von Client und Server vertauscht. Der Webserver versucht eine Verbindung zum Debug Client aufzubauen. Das kommt uns hier zu Gute, weil Programme im Container raustelefonieren dürfen aber umgekehrt nicht beliebig erreichbar sind.
Einen Server einrichten
Zuerst muss unter File -> Settings > Languages & Frameworks -> PHP -> Servers ein neuer Server angelegt werden. Da ich meinen Container mit docker run –rm -ti –name web -p 8080:80 -v /home/cgd/Projects/Docker/Example:/var/www/html:ro –link db3:db phpmysqli gestartet habe ist er auf Port 8080 lokal erreichbar. Ich lege meinen Server names „Docker“ also mit Host 127.0.0.1 und Port 8080 an und wähle als Debugger Xdebug. Abschließend definiere ich noch das Path Mapping von /home/cgd/Projects/Docker/Example auf /var/www/html – steht ja so auch alles im Docker-Aufruf schon drin 🙂 Dann lohnt noch ein prüfender Blick unter File -> Settings > Languages & Frameworks -> PHP -> Debug. Dort sollte die Option „Ignore external connections through unregistered server configurations“ aus und „Xdebug – Can accept external connections“ ein geschaltet sein. Naja, und das der Port auch hier auf 9000 stehen sollte muss ich hoffentlich nicht wirklich erwähnen…
Eine Debug Configuration einrichten
Als nächstes muss eine sogenannte „Debug Configuration“ eingerichtet werden. Run -> Edit Configurations öffnet den entsprechenden Dialog. Mit dem Plus-Zeichen eine neue „PHP Remote Debug“ Configuration anlegen und benennen; „Docker“, zum Beispiel, wenn man besonders kreativ ist. Einen Server („Docker“) auswählen und noch einen Ide key vergeben. Ich verwende XDEBUG_IDEA aber es kann jeder beliebige String verwendet werden; Sonderzeichen sollte man dabei vermeiden.
Wählt man nun Run -> Debug ‚Docker‘ fängt IDEA an auf eingehende Remote Debug Verbindungen zu lauschen. In der Debug-Konsole sollte eine entsprechende Meldung stehen.
Den Debugger starten
Wird jetzt ein Aufruf an den Webserver mit dem Parameter „XDEBUG_SESSION_START=XDEBUG_IDEA“ geschickt nimmt Xdebug Kontakt zur IDE auf. Wenn alles glatt geht pausiert die Verarbeitung des Programms jetzt je nach Konfiguration in der ersten Zeile, am ersten Breakpoint oder beim ersten Fehler.
Noch mehr Details und Informationen zu weiteren Helferlei gibt es in der Dokumentation zum Remote Debugging von Xdebug. Happy Debugging!
Das Titelbild stammt von https://www.flickr.com/photos/xmodulo/14098888813 und steht unter der CC BY 2.0 Lizenz.
Funktioniert, stark, danke dir!
Danke! Läuft super!