La Containerization, un termine che in Italiano potrebbe essere tradotto con "containerizzazione", è una tecnologia che ha guadagnato sempre più attenzione negli ultimi anni, diventando parte integrante del bagaglio tecnico di ogni sviluppatore. Questa innovativa architettura consente di ottimizzare lo sviluppo delle applicazioni velocizzandolo. Grazie a essa possiamo suddividere un'applicazione in servizi più piccoli, noti come images (immagini), sfruttando al meglio le risorse hardware disponibili.
In questo mini-tutorial, esploreremo un modello di file docker-compose che ci permetterà di configurare l'ambiente della nostra applicazione e di eseguire facilmente tutti i comandi necessari per completare il setup in modo semplice ed elegante. Come indicato nel titolo, ci concentreremo sulla creazione di un ambiente ideale per un'applicazione PHP servita da Apache, integrando il classico database MySQL e un tool indispensabile come phpMyAdmin.
Utilizzando Docker, possiamo gestire facilmente un ambiente configurato in questo modo. Sebbene ricordi il tradizionale ambiente LAMP, offre una portabilità e una facilità di gestione significativamente superiori. Ogni servizio opererà come un microservizio, consentendoci di creare un unico file YAML (il docker-compose.yml
) che genererà i vari servizi mantenendoli isolati l'uno dall'altro.
Uno dei principali vantaggi offerti dai container è la loro scalabilità, utile sia in un contesto di integrazione continua (CI/CD) sia per la condivisione delle immagini tra i membri del team di sviluppo. Condividere il file docker-compose.yml
nel repository Git consente a ciascun membro di eseguire un ambiente identico per lo sviluppo e il testing dell'applicazione, indipendentemente dal sistema operativo utilizzato.
Cosa vedremo in questa guida
- Creazione di un container locale con PHP e Apache.
- Test del container utilizzando un semplice script PHP.
- Creazione di un database MySQL e verifica della sua funzionalità con PHP.
- Conoscenze basilari di PHP e un minimo di SQL.
- Nozioni fondamentali su Docker e sul funzionamento dei container.
- Familiarità con i comandi Linux
Utilizzeremo il Docker Hub, l'archivio pubblico delle immagini, per i nostri container.
Prerequisiti per la creazione di un ambiente PHP
Prima di iniziare, assicuriamoci di avere installato Docker sul nostro computer e di soddisfare i seguenti requisiti:
Diamo quindi il via all'installazione e all'avvio di Docker!
Installazione e avvio di Docker
Dopo aver scaricato e installato Docker, è il momento di avviare l'applicazione desktop per verificare che l'engine sia in esecuzione correttamente. Per operare una rapida verifica, apriamo il terminale e eseguiamo il seguente comando:
docker version
Dovremmo ricevere una risposta simile a questa:
$ docker version
Client:
Cloud integration: v1.0.35+desktop.13
Version: 26.1.1
API version: 1.45
Go version: go1.21.9
Git commit: 4cf5afa
Built: Tue Apr 30 11:48:43 2024
OS/Arch: windows/amd64
Context: default
Server: Docker Desktop 4.30.0 (149282)
Engine:
Version: 26.1.1
API version: 1.45 (minimum version 1.24)
Go version: go1.21.9
Git commit: ac2de55
Built: Tue Apr 30 11:48:28 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.31
GitCommit: e377cd56a71523140ca6ae87e30244719194a521
runc:
Version: 1.1.12
GitCommit: v1.1.12-0-g51d5e94
docker-init:
Version: 0.19.0
GitCommit: de40ad0
A questo punto proviamo a visualizzare i container attivi. Naturalmente, l'elenco dovrebbe risultare vuoto se non abbiamo ancora avviato alcun container.
Creazione del file docker-compose.yml
Il file docker-compose.yml
ci consente di configurare in modo pragmatico il nostro progetto, definendo i servizi e permettendo la replicazione infinita dei nostri container. Per il nostro progetto utilizzeremo immagini ufficiali provenienti dal Docker Hub, come PHP Apache e MySQL.
Iniziamo creando un file chiamato docker-compose.yml
all'interno del nostro progetto e definendo la versione di Docker Compose che intendiamo utilizzare. Proseguiremo quindi a definire i vari servizi che utilizzeremo, aggiungendo passo passo le direttive necessarie per la loro configurazione.
version: 'x.x'
services:
php-apache-environment:
container_name:
Configurazione di PHP e Apache
Per il setup del nostro container PHP + Apache, impostiamo alcune direttive di base:
- Nome del container: questo è semplicemente un identificatore utile per alcune operazioni. Se non specificato, Docker assegnerà un nome casuale. Per il nostro caso, utilizzeremo
php-apache
- Immagine di partenza: useremo una delle immagini ufficiali disponibili sul Docker Hub. In questo caso, per il nostro servizio, utilizzeremo
php:8.4-apache
- Volume: questa direttiva stabilisce la corrispondenza tra la nostra cartella di lavoro e la directory corrispondente nel container per Apache.
Nel nostro caso, la configurazione sarà:
volumes:
- ./php/src:/var/www/html/
Qui, il servizio risponde sulla porta 80
8000
localhost:8000
Ecco la nostra prima versione del file docker-compose.yml
version: 'x.x'
services:
php-apache-environment:
container_name: php-apache
image: php:8.4-apache
volumes:
- ./php/src:/var/www/html/
ports:
- 8000:80
Avvio del container
Testiamo subito la configurazione! Eseguiamo il comando seguente per avviare i nostri servizi:
docker-compose up
Monitoraggio dei container in Docker Desktop
Aprendo Docker Desktop vedremo che i container sono in esecuzione. Questo significa che tutto sta procedendo come previsto. Adesso possiamo testare il nostro ambiente aprendo il browser e navigando verso http://localhost:8000
. Se visualizziamo un errore non preoccupiamoci: significa semplicemente che il servizio php-apache
è attivo e funzionante!
Eseguiamo un semplice script PHP
Nel nostro file docker-compose.yml
abbiamo definito il volume come segue:
volumes:
- ./php/src:/var/www/html/
Questo implica che i file del nostro progetto devono trovarsi all'interno della sottodirectory php/src
. Creiamo quindi un semplice file index.php
al suo interno:
<?php
echo "Hello there, this is a PHP Apache container";
?>
Aggiorniamo la pagina nel browser e.. ci siamo! Abbiamo ufficialmente containerizzato il nostro progetto PHP.
Configurazione del Container MySQL
È il momento di aggiungere il servizio MySQL al nostro progetto in modo da avere un database da utilizzare con PHP. Nel nostro file docker-compose.yml
aggiungiamo una nuova sezione chiamata db
. Imposteremo anche le credenziali di accesso al database, come nome utente e password. Ecco come si presenterà la configurazione:
db:
container_name: db
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: MYSQL_ROOT_PASSWORD
MYSQL_DATABASE: MY_DATABASE
MYSQL_USER: MYSQL_USER
MYSQL_PASSWORD: MYSQL_PASSWORD
ports:
- "9906:3306"
Aggiungiamo la direttiva restart: always
per garantire che il servizio venga riavviato ogni volta che apportiamo modifiche al file.
Creazione di un Dockerfile
Docker può generare automaticamente le immagini a partire da un Dockerfile. Questo è un semplice file di testo che contiene comandi che "assemblano" un'immagine. Nel nostro caso vogliamo che l'interprete PHP nell'immagine php:8.4-apache
, specificata nel nostro docker-compose.yml
, possa connettersi a MySQL. Per fare ciò, dobbiamo installare alcune librerie. Creiamo quindi un file vuoto chiamato Dockerfile
(senza estensione) e aggiungiamo il seguente contenuto:
FROM php:8.4-apache
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
RUN apt-get update && apt-get upgrade -y
Inoltre, aggiungeremo una nuova direttiva al nostro docker-compose.yml: depends_on
. Essa indica a Docker che un servizio dipende da un altro, assicurando che vengano avviati nell'ordine corretto.
Ecco come dovrebbe apparire il nostro docker-compose.yml
aggiornato:
version: 'x.x'
services:
php-apache-environment:
container_name: php-apache
build:
context: ./php
dockerfile: Dockerfile
depends_on:
- db
volumes:
- ./php/src:/var/www/html/
ports:
- 8000:80
db:
container_name: db
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: MYSQL_ROOT_PASSWORD
MYSQL_DATABASE: MYSQL_DATABASE
MYSQL_USER: MYSQL_USER
MYSQL_PASSWORD: MYSQL_PASSWORD
ports:
- "9906:3306"
Avvio dei Container
Ora possiamo eseguire il comando seguente per scaricare le immagini e avviare i container:
docker-compose up
Dovremmo vedere anche il servizio MySQL attivo nel nostro Docker Desktop.
Testiamo la connessione tra applicazione PHP e database
Modifichiamo il nostro file index.php
per testare la connessione al servizio MySQL che abbiamo appena lanciato. Aggiungiamo il seguente codice:
<?php
// index.php
// Il nome del servizio definito in docker-compose.yml.
$host = 'db';
$user = 'MYSQL_USER';
$pass = 'MYSQL_PASSWORD';
$conn = new mysqli($host, $user, $pass);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
} else {
echo "Connected to MySQL server successfully!";
}
?>
Salviamo il file e aggiorniamo la pagina su http://localhost:8000
Installazione di phpMyAdmin
Ora che la connessione a MySQL è stata stabilita, potremmo trarre grande beneficio dall'uso di phpMyAdmin per gestire il database. Esiste già un'immagine pronta da utilizzare, dobbiamo solo configurarla. Aggiungiamo quindi una nuova sezione al nostro docker-compose.yml
per phpMyAdmin:
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- '8080:80'
restart: always
environment:
PMA_HOST: db
depends_on:
- db
Abbiamo specificato di voler utilizzare l'immagine phpmyadmin/phpmyadmin
, di mappare la porta 8080
e di utilizzare il servizio MySQL specificato in PMA_HOST: db
. Eseguiamo di nuovo docker-compose up
per fare il pull e avviare questo nuovo container. Puntiamo poi il browser verso http://localhost:8080
e dovremmo vedere la pagina di login di phpMyAdmin.
Per accedere, utilizziamo le credenziali impostate nel docker-compose.yml
sotto la sezione db
(cioè MYSQL_USER e MYSQL_PASSWORD).
Conclusioni: containerizzare un progetto PHP/Apache e MySQL in pochi minuti
In questo mini-tutorial, abbiamo visto come containerizzare il nostro progetto PHP/Apache e MySQL in pochi minuti. Questo è solo l'inizio: Docker ci offre enormi vantaggi come la possibilità di aggiungere servizi come Redis al nostro progetto e la sua portabilità. Includendo i file docker-compose.yml
e Dockerfile nel repository Git possiamo riprendere lo sviluppo del nostro progetto ovunque ci troviamo.