Capita sempre più spesso di avere più progetti Laravel in corso che richiedono versioni e configurazioni diverse di PHP o semplicemente non sempre si può aggiornare il proprio sistema LAMP per un semplice test. Per questo motivo ho iniziato a lavorare con Docker per separare le diverse installazioni. In questo articolo, vi propongo il processo di dockerizzazione di un'applicazione Laravel, in ambiente Windows, i comandi essenziali e le configurazioni ottimali per sfruttare appieno il potenziale di Docker con Laravel.
Docker
Nell'era dello sviluppo software agile e della distribuzione continua, Docker è sicuramente uno degli strumenti indispensabile per un developer. La sua capacità di containerizzare le applicazioni, garantendo consistenza e isolamento tra ambienti, ha rivoluzionato il modo in cui sviluppiamo e distribuiamo il software.
Laravel, uno dei framework PHP più amati, non fa eccezione. Integrare Docker nel flusso di lavoro di Laravel offre numerosi vantaggi:
- Ambienti di sviluppo coerenti: Dimentica i problemi di "funziona sulla mia macchina". Docker assicura che il tuo ambiente di sviluppo sia identico a quello di produzione.
- Distribuzione semplificata: Impacchetta la tua applicazione Laravel e le sue dipendenze in un singolo contenitore, facilitando la distribuzione su qualsiasi infrastruttura.
- Scalabilità e gestione delle dipendenze: Gestisci facilmente le dipendenze e scala la tua applicazione senza preoccupazioni.
Un container per Laravel
Per gli scopi di questo articolo partiamo da una applicazione Laravel esistente e creiamo una cartella docker che conterrà tutto quello che ci serve.
Per avere un ambiente di sviluppo adatto a Laravel, ci occorre un server http, un interprete PHP, un servizio mySql. A questo stack minimo, noi aggiungeremo il tool phpMyAdmin e attiveremo Xdebug sul PHP.
Questo metodo è chiaramente alternativo all'utilizzo di
Laravel Sail, ma mio avviso è più versatile e permette di gestire più facilmente l'ambiente di sviluppo con un utilizzo diretto di Docker (tecnologia che può facilmente essere riutilizzata) senza intermediazioni.
Il server Nginx
Nella cartella creiamo un file docker-compose.yml e nel file iniziamo a inserire le definizioni dei container necessari (attenzione: in questo tipi di file è necessario usare il tab per l'indentazione):
services:
nginx:
image: nginx:latest
container_name: nginx
volumes:
- ./../:/var/www/html
- ./default.conf:/etc/nginx/conf.d/default.conf
ports:
- "8080:80"
links:
- phpfpm
Le righe precedenti, definiscono un server nginx a partire dall'immagine più recente disponibile, aggiunge due volumi (uno con la root del nostro progetto e un altro con un file di configurazione che vedremo tra poco), espone la porta 80 del container sulla porta 8080 del nostro host, infine indica che questo servizio dipende da un servizio phpfpm che ancora dobbiamo definire.
Nella stessa cartella docker, creiamo un file default.conf con i parametri di configurazione del server nginx
- indicazione della porta
- indicazione della cartella di root
- indicazione del file di avvio (index.php, prioritario rispetto a index.html)
- ...
server {
listen 80;
charset utf-8;
root /var/www/html/public;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass phpfpm:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
L'interprete PHP
Nel file docker-compose.yml aggiungiamo la definizione di un nuovo container:
phpfpm:
container_name: phpfpm
build:
context: ./..
dockerfile: docker/Dockerfile
volumes:
- ./../:/var/www/html
- ./xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
links:
- mysql
La definizione di questo container è spostata in un Dockerfile specifico. anche questo servizio aggiunge due volumi (uno con la root del nostro progetto e un altro con un file di configurazione di xdebug che vedremo tra poco), infine indica che questo servizio dipende da un servizio mysql che ancora dobbiamo definire.
Nella stessa cartella docker, creiamo un file Dockerfile con i parametri di configurazione del nostro container phpfpm:
FROM php:8.2-fpm-alpine
RUN apk update \
&& apk upgrade \
&& apk add \
linux-headers \
$PHPIZE_DEPS \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& docker-php-ext-install pdo_mysql \
&& apk del $PHPIZE_DEPS \
&& rm -rf /var/cache/apk/*
Il container quindi è basato sull'immagine PHP 8.2 Fpm Alpine (ma la versione Laravel su cui state lavorando potrebbe richiede una versione diversa di PHP), a cui è aggiunto Xdebug e il supporto per mysql.
Per la configurazione di Xdebug, sempre nella cartella docker, creiamo un file xdebug.ini:
zend_extension=xdebug.so
xdebug.mode=debug,develop
xdebug.start_with_request=yes
xdebug.discover_client_host=1
xdebug.cli_color=1
xdebug.log_level=0
Il server MySQL
Nel file docker-compose.yml aggiungiamo la definizione di un nuovo container:
mysql:
image: mysql:latest
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: app_db
ports:
- "6033:3306"
volumes:
- ./.data:/var/lib/mysql
Le righe precedenti, definiscono un server mysql a partire dall'immagine più recente disponibile, definisce la password di root e il nome del database da creare (se non già presente), espone la porta 3306 del container sulla porta 6033 del nostro host, infine aggiunge un volume (la sottocartella .data della nostra cartella docker che conterrà i dati del database in modo da garantire la persistenza anche se distrugge e si ricostruisce il container.
Il tool phpMyAdmin
Sempre nel file docker-compose.yml infine aggiungiamo la definizione di un nuovo container per phpMyadmin, esposto sulla porta 8081 del nostro host. anche questo servizio dipende dal servizio mysql:
phpmyadmin:
image: phpmyadmin:latest
container_name: pma
environment:
PMA_HOST: mysql
PMA_PORT: 3306
PMA_ARBITRARY: 1
restart: always
ports:
- 8081:80
links:
- mysql
La configurazione di Laravel
Adeguiamo la configurazione di Laravel per la corretta connessione al database, quini nel file .env, modifichiamo le righe seguenti:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=app_db
DB_USERNAME=root
DB_PASSWORD=root
Avviamo il container
La definizione di quanto necessario è terminata, non ci resta quindi che avviare la creazione del container. Da terminale, posizioniamoci nella cartella docker che abbiamo creato e avviamo il seguente comando, sostituendo nome_progetto con il nome che vogliamo assegnare al nostro container:
docker-compose -f docker-compose.yml -p nome_progetto pull && \
docker-compose -f docker-compose.yml -p nome_progetto build --no-cache && \
docker-compose -f docker-compose.yml -p nome_progetto up -d --remove-orphans
Salvo errori, in Docker Desktop dovreste avere vista simile a questa:
E' possibile raggiungere la homepage del progetto su localhost:8080 e phpMyAdmin all'indirizzo localhost:8081 (o in alternativa cliccando in corrispondenza delle porte indicate):
Se fosse necessario modificare la configurazione dei container sarà poi necessario ricostruirli. Automatizziamo il processo, creando un file batch (siamo in ambiente Windows) con tutto quanto necessario per distruggere il container e ricostruirli, velocemente. sempre nella cartella
docker, creiamo un file
create.bat con le seguenti istruzioni:
SET NOME_PROGETTO=laravel_test
docker-compose -f docker-compose.yml -p %NOME_PROGETTO% down
docker-compose -f docker-compose.yml -p %NOME_PROGETTO% rm -f
docker-compose -f docker-compose.yml -p %NOME_PROGETTO% pull
docker-compose -f docker-compose.yml -p %NOME_PROGETTO% build --no-cache
docker-compose -f docker-compose.yml -p %NOME_PROGETTO% up -d --remove-orphans
docker image prune -f --filter="dangling=true"
Ogni volta che avvieremo il file batch, avremo che:
- interrompe e rimuove i container esistenti e le reti create
- cancella i container dei servizi stoppati
- scarica le immagini necessarie
- fa la build dei servizi (ignorando la cache in modo da essere sicuri di avere sempre immagini recenti)
- crea e avvia i container, rimuovendo le dipendenze non più necessarie
- rimuove le immagini non più utili e non collegate ad altre immagini
Naturalmente questi comandi non cancellano i dati del nostro database, che sono al sicuro nella cartella
docker/.data, che magari sarebbe utile da escludere da una eventuale sincronizzazione github.
I comandi artisan
Per completare l'ambiente di sviluppo Laravel, non ci resta che gestire i comandi artisan. Questi vanno lanciati nell'ambiente docker, quindi da terminale. Ad esempio per le migrazioni occorre digitare:
docker exec phpfpm php artisan migrate
e in modo similare tutti gli altri che servono.
Conclusioni
Commenti
Posta un commento