Installare XDebug in un container Docker ed eseguire il debug del codice con VS Code

Il debug è una fase essenziale nel ciclo di sviluppo del software in quanto consente di individuare e correggere gli errori e i difetti presenti nel codice. Grazie al debugging, gli sviluppatori possono migliorare la qualità del software, rendendolo più affidabile, performante e sicuro. Identificare e risolvere i bug in modo tempestivo non solo ottimizza il processo di sviluppo, ma riduce anche i costi associati alla manutenzione e al supporto post-lancio. Inoltre, il debug favorisce una comprensione più approfondita del funzionamento del software, permettendo agli sviluppatori di acquisire competenze più avanzate e di implementare soluzioni più efficaci in futuro.

Perchè Docker

Come ho già avuto modo di scrivere nel precedente articolo presente su questo blog, Docker permette di creare ambienti coerenti e consistenti nei vari contesti: sviluppo, collaudo e produzione, a prescindere dall’architettura di esecuzione.

Questo strumento è entrato prepotentemente nel ciclo di sviluppo grazie alla sua semplicità di installazione ed utilizzo sia da parte dei professionisti più esperti quanto dei neofiti che si stanno avvicinando alla programmazione.

Anche i DevOps ne decantano le lodi considerando che anche il processo di scaling dei container è stato semplificato, ma non banalizzato, attraverso due distinti ma entrambi validi orchestratori: Swarm e Kubernetes.

Perchè XDebug

PHP è uno dei linguaggi di programmazione server side più usati al mondo, lo dicono le statistiche, non io.

E come ogni buon linguaggio di programmazione che si rispetti, tra croce e delizie, ha i propri tool di debug del codice.

Per progetti semplici o script stand-alone, il classico print_r, var_dump e gli error_log, possono bastare, ma quando si lavora su progetti più complessi, questi comandi non sono più sufficienti. Quindi ci vengono in soccorso i debugger. I due più conosciuti appunto sono XDebug e ZendDebugger.

Per qualche tempo, circa 15 anni fa ho usato Zend Debugger ma, come accade ad ogni professionista, ho scelto XDebug con cui mi sento di più a mio agio in quanto l’ho visto maturare nel tempo e diventare uno strumento sempre più diffuso.

Perchè VSCode

Ho utilizzato per tanti anni Eclipse con numerose estensioni per programmare nei più disparati linguaggi di programmazione, poi sono passato per quasi una decina di anni ad IntelliJ Idea con il quale non mi trovavo affatto male, anzi di tanto in tanto mi manca, infine sono passato a VSCode per allinearmi alle abitudini del team con il quale quotidianamente lavoro in Axio Studio.

Base di partenza

In questo articolo non spiegherò le basi di Docker o della programmazione PHP ma semplicemente come installare, configurare e integrare XDebug con Visual Studio Code. Per farlo si deve partire comunque da una base.

La base di partenza quindi sarà un Dockerfile già esistente:

FROM php:8.2.10-apache
USER www-data
COPY . .
EXPOSE 80
CMD ["apache2-foreground"]

Per chi ha avuto l’occasione di leggere il mio articolo su Docker comprenderà buona parte dei comandi qui sopra.

In pratica, ho creato un’immagine docker basata su php versione 8.2.10 in esecuzione su Apache copiando tutto il contenuto della directory di contesto nella /var/www/html del container che espone il servizio httpd sulla porta 80 con diritti dell’utente www-data del container.

Ecco non potevo essere più sintetico!

Installare XDebug nel Dockerfile

La prima azione da svolgere è aggiungere i comandi opportuni per consentire al’immagine descritta sopra di ospitare anche XDebug.

FROM php:8.2.10-apache

USER root
RUN pecl install xdebug && \
    docker-php-ext-enable xdebug

USER www-data
COPY . .
EXPOSE 80
CMD ["apache2-foreground"]

Per installare XDebug, eleviamo i diritti di esecuzione nell’immagine in fase di creazione a livello di utente root.

Quindi installiamo l’estensione di xdebug tramite PECL (Libreria delle Estensioni per PHP manutenuta dalla Community, è esattamente il significato di PECL).

E la abilitiamo attraverso il comando integrato nell’immagine docker di PHP docker-php-ext-enable.

Già provando a fare la build del container xdebug sarà disponibile, seppur con una configurazione di default e quasi inutilizzabile.

Per verificare quanto scrivo è sufficiente creare un file php nella root e riportare il codice mostrato di seguito:

<?php
xdebug_info();

Nota che il codice sopra non funzionerà se l’estensione xdebug non è installata.

Altrimenti il risultato sarà una pagina simile all’output del metodo php_info() per chi ha confidenza con questo linguaggio di programmazione.

Configurare XDebug

La configurazione di xdebug è altrettanto semplice ma richiede degli accorgimenti.

Il primo passo è creare un file di configurazione per XDebug nella root del progetto, accanto al Dockerfile.

zend_extension=xdebug

[xdebug]
xdebug.remote_enable=on
xdebug.remote_autostart = 1
xdebug.mode=develop,debug
xdebug.client_host=host.docker.internal
xdebug.start_with_request=yes

xdebug.log=/var/www/html/xdebug.log
xdebug.idekey=VSCODE
xdebug.client_port=9003

error_reporting=E_ALL

Spiegazione delle singole chiavi

Se sei un appassionato di Stack Overflow e del Copia & Incolla, puoi saltare questo paragrafo, altrimenti, fidati, è tutta conoscenza che accrescerà il tuo bagaglio di competenze professionali.

zend_extension=xdebug

Abilita l’estensione xdebug. Per chi si domandasse cosa sia quello zend in testa alla riga, riduco il concetto al solo far presente che Zend è la società che ha inventato PHP, quando ancora significava Personal Home Page.

xdebug.remote_enable=on

Questa chiave è fondamentale, quando si tira su un’immagine Docker è come se il codice fosse eseguito nel Cloud, quindi in remoto. Solo se impostato a on, potrà permettere il debug da remoto.

xdebug.remote_autostart = 1

Grazie a questo comando il debugger si attiverà ad ogni richiesta ricevuta dal nostro container.

Nota importante: per questioni di performance, questo valore va impostato a 0 in ambiente di stage. Inutile evidenziare che in ambiente di produzione XDebug non deve essere installato.

xdebug.mode=develop,debug

È la modalità con cui si vuole attivare xdebug, ci sono diverse modalità, tutte combinabili tra di loro.

La configurazione proposta permette il debug passo-passo ed una serie di agevolazioni per gli sviluppatori con dei messaggi di errore più ricchi di dettagli.

xdebug.client_host=host.docker.internal

È l’indirizzo IP o il nome host dal quale può essere stabilita la connessione, se non si sa bene come cambiarlo ed il tutto deve funzionare su una macchina locale, lasciarlo esattamente con questo valore.

xdebug.start_with_request=yes

Se impostato a yes, il processo xdebug parte prima che la prima riga di codice PHP venga eseguita.

xdebug.log=/var/www/html/xdebug.log

Tutti i log di xdebug saranno prodotti nel file menzionato, per lo scopo di questo articolo va bene che venga generato nella root applicativa, solitamente va messo in una directory temporanea.

xdebug.idekey=VSCODE

Eseguendo il debug da VSCode, come obiettivo di questo articolo, è necessario che questo valore sia lasciato intatto.

xdebug.client_port=9003

Per una configurazione ancora più spinta si può consultare la documentazione ufficiale molto ricca e altrettanto chiara.

Applicazione della configurazione di XDebug

Aggiungiamo al Dockerfile il comando per copiare il file di configurazione nel percorso in cui sono applicate anche tutte le altre configurazioni di PHP.

Ed esponiamo la porta 9000.

FROM php:8.2.10-apache

USER root
RUN pecl install xdebug && \
    docker-php-ext-enable xdebug

COPY ./xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

USER www-data
COPY . .
EXPOSE 80, 9000
CMD ["apache2-foreground"]

Possiamo a questo punto aprire VSCode e configurare l’ambiente per cominciare con il debug del codice.

Configurare VSCode

Dalla barra degli strumenti principale di VSCode bisogna accedere alla sezione di debug ed aggiungere una nuova configurazione.

Sarà aperto un file JSON con le varie configurazioni.

Nel blocco configurations innestare il seguente codice:

{
    "name": "Listen for Xdebug",
    "type": "php",
    "request": "launch",
    "port": 9003,
    "pathMappings": {
        "/var/www/html": "${workspaceFolder}"
    }
},

Premere il tasto F5 e l’editor è pronto per una completa sessione di debug, dall’inizio alla fine!

Conclusioni

Con l’installazione di XDebug in un container Docker e l’integrazione con VS Code, abbiamo esplorato un approccio potente ed efficiente per eseguire il debug del codice PHP. Questa combinazione non solo ottimizza il flusso di lavoro degli sviluppatori, ma consente anche un ambiente di sviluppo flessibile e replicabile.

Ora che sono stati coperti i passaggi fondamentali per configurare questo setup, mi piacerebbe conoscere le vostre esperienze e opinioni.

Quali sono le vostre migliori pratiche per il debugging in ambienti containerizzati?

Avete riscontrato sfide specifiche e come le avete superate?

Condividete i vostri suggerimenti e trucchi nei commenti, così possiamo continuare a migliorare e innovare insieme.