In questo articolo, Docker Compose – Creazione di un ambiente con Apache, PHP, MySQL e phpMyAdmin, vediamo come utilizzare Docker Compose per creare un ambiente di sviluppo con Apache, PHP, MySQL e phpMyAdmin.
- Introduzione a Docker e Docker Compose
- Vantaggi di usare Docker Compose
- Teoria di Docker Compose
-
Creazione dell’ambiente con Apache – PHP, MySQL e phpMyAdmin
- Step 1: Creazione di un ambiente di base con Apache-PHP e MySQL
- Step 2: Creazione del Dockerfile
- Step 3: Creazione della cartella sorgenti per i file PHP
- Step 4: Avvio dell’applicazione
- Step 5: Testare il Funzionamento
- Step 6: Aggiungere phpMyAdmin per la gestione del database
- Step 7: Rilanciare Docker Compose
- Step 8: Testare phpMyAdmin
- Test completo dell’applicazione
- Vantaggi di Docker Compose: Un Solo Comando per Ampliare l’Applicazione
- Conclusione
Introduzione a Docker e Docker Compose
Cos’è Docker Compose?
Docker Compose è uno strumento che consente di definire e gestire applicazioni multi-container. Con un singolo file YAML (docker-compose.yml
), è possibile configurare, eseguire e gestire più contenitori contemporaneamente, semplificando notevolmente la gestione di ambienti complessi. Docker Compose è particolarmente utile quando si lavora con applicazioni che richiedono più servizi, come database, server web e applicazioni frontend.
Il file docker-compose.yml
è un file di configurazione scritto in formato YAML (YAML acronimo di “YAML Ain’t Markup Language” è un linguaggio di serializzazione dei dati utilizzato per scrivere file di configurazione per il deployment dell’infrastruttura) che consente di definire, gestire e avviare più container Docker in maniera coordinata, come se fossero un’unica applicazione multi-servizio.
Vantaggi di usare Docker Compose
- Gestione semplificata di più container: Docker Compose permette di avviare e gestire facilmente più container con un singolo comando.
-
Definizione delle dipendenze: Le dipendenze tra i servizi sono esplicitamente definite nel file
docker-compose.yml
, semplificando la configurazione. - Facilità di scalabilità: È possibile scalare i servizi aggiungendo o rimuovendo container con un solo comando.
- Ambientazioni riproducibili: Docker Compose consente di creare ambienti che possono essere facilmente replicati su altre macchine, assicurando che i team di sviluppo lavorino con la stessa configurazione.
Teoria di Docker Compose
File docker-compose.yml
Il cuore di Docker Compose è il file docker-compose.yml
, che descrive i servizi, le reti e i volumi utilizzati dall’applicazione. Ecco una panoramica della sintassi del file:
version: "xxx"
services:
servizio 1:
image: immagine:tag
ports:
- "porta_host:porta_container"
volumes:
- locale:container
environment:
VARIABILE: valore
servizio 2:
image: immagine:tag
ports:
- "porta_host:porta_container"
volumes:
- locale:container
environment:
VARIABILE: valore
servizio n:
......
networs:
......
Concetto di Servizi, Reti e Volumi
-
Servizi: Ogni contenitore che esegue un’applicazione o una parte di essa è definito come un “servizio”. In questo caso,
apache-php
,mysql
ephpmyadmin
sono tutti servizi. - Reti: Docker Compose crea automaticamente una rete privata per ogni applicazione, a meno che non venga configurato diversamente.
-
Volumi: I volumi sono utilizzati per persistere i dati tra i riavvii dei contenitori. In questo esempio, il volume
./html
è montato su/var/www/html
per permettere la modifica dei file PHP in locale.
Per quanto riguarda Servizi e Volumi i concetti sono già stati esplicitati nelle GUIDE PRECEDENTI. Esplicitiamo il concetto di RETE
Il concetto di reti in Docker Compose riguarda la gestione della comunicazione tra i contenitori (container) che fanno parte della stessa applicazione. Quando si avvia un’applicazione multi-container tramite Docker Compose, Docker crea automaticamente una rete virtuale privata in cui i container possono comunicare tra di loro. Questo isolamento è utile per garantire che i contenitori di un’applicazione non interferiscano con quelli di altre applicazioni che potrebbero essere in esecuzione sulla stessa macchina.
Cos’è una rete in Docker Compose?
Una rete in Docker Compose è un’entità virtuale che consente ai contenitori di comunicare tra loro. Ogni contenitore che appartiene alla stessa rete può “vedere” e comunicare con gli altri contenitori della stessa rete utilizzando i loro nomi di servizio (definiti nel file docker-compose.yml
), come se fossero nomi host.
Se non viene configurata esplicitamente una rete, Docker Compose crea automaticamente una rete privata e di default per ogni applicazione. La rete sarà visibile solo ai contenitori definiti nel file docker-compose.yml
di quell’applicazione, impedendo la comunicazione con altre applicazioni in esecuzione sulla stessa macchina.
Comportamento di Default
Quando si usa Docker Compose senza configurare reti esplicitamente, Docker crea una rete privata con il nome del progetto, a cui i container sono automaticamente connessi. Questo significa che i contenitori possono comunicare tra loro, ma non con i contenitori di altre applicazioni.
Esempio di un file docker-compose.yml
con la configurazione di rete di default:
version: "3"
services:
web:
image: nginx
ports:
- "8080:80"
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: example
In questo caso, Docker Compose crea una rete chiamata nomeprogetto_default
(dove “nomeprogetto” è il nome della cartella o del progetto) e connette i contenitori web
e db
a questa rete. Entrambi i container possono comunicare tra loro utilizzando i nomi di servizio (web
e db
), come nel caso di una connessione al database MySQL dal container web
usando db
come hostname.
Come personalizzare le reti in Docker Compose?
Docker Compose consente anche di definire reti personalizzate, che danno un maggiore controllo sul comportamento di rete tra i contenitori. Si può definire una rete con un nome specifico, decidere se utilizzare una rete bridge
(la rete predefinita di Docker) o altre tipologie di rete, e collegare i tuoi contenitori a queste reti.
Ecco un esempio di configurazione di rete personalizzata:
version: "3"
services:
web:
image: nginx
networks:
- frontend
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: example
networks:
- backend
phpmyadmin:
image: phpmyadmin
environment:
PMA_HOST: db
networks:
- frontend
- backend
networks:
frontend:
backend:
In questo esempio, sono state create due reti personalizzate: frontend
e backend
. I contenitori web
e phpmyadmin
sono collegati alla rete frontend
, mentre db
è collegato alla rete backend
. Inoltre, phpmyadmin
è connesso sia alla rete frontend
che alla rete backend
.
Cosa accade con le reti personalizzate?
- I contenitori sulla stessa rete (ad esempio,
web
ephpmyadmin
nella retefrontend
) possono comunicare facilmente tra loro. - I contenitori su reti diverse (ad esempio,
web
sulla retefrontend
edb
sulla retebackend
) non possono comunicare direttamente tra di loro, a meno che non venga configurato un collegamento esplicito tra le reti. - Nel caso del servizio
phpmyadmin
, esso è connesso sia alla retefrontend
che a quellabackend
, quindi può comunicare sia con il contenitoreweb
che condb
.
Esempio pratico: comunicazione tra servizi
Immaginiamo di voler creare un’applicazione che include un server web (Apache con PHP), un database (MySQL) e una interfaccia di gestione (phpMyAdmin). Si può utilizzare Docker Compose per definire i servizi e le reti. Se non si specifica una rete personalizzata, Docker Compose creerà automaticamente una rete privata.
Tuttavia, se si ha bisogno di configurare una rete separata per isolare la comunicazione tra i servizi, si può fare come mostrato nell’esempio precedente.
Scenario senza rete personalizzata:
- I servizi possono comunicare tra di loro tramite il nome del servizio, ma tutti sono sulla stessa rete, quindi sono più “esposti”.
Scenario con reti personalizzate:
- I contenitori
web
ephpmyadmin
sono sulla stessa rete (frontend
) e possono comunicare facilmente tra loro, ma non possono comunicare direttamente condb
, a meno che non si colleghino alla retebackend
o non venga creato un link esplicito.
Riepilogo
- Rete di default: Docker Compose crea automaticamente una rete per ogni applicazione, a meno che non venga configurato diversamente.
- Reti personalizzate: Si possono definire reti personalizzate per un controllo più granulare sulla comunicazione tra i contenitori.
- Sicurezza e isolamento: Le reti personalizzate possono essere utilizzate per isolare i contenitori, migliorando la sicurezza e l’affidabilità dell’applicazione.
- Comunicazione tra i contenitori: I contenitori sulla stessa rete possono comunicare tra di loro tramite i loro nomi di servizio.
Questo approccio rende Docker Compose uno strumento potente per gestire applicazioni complesse e sicure.
Creazione dell’ambiente con Apache – PHP, MySQL e phpMyAdmin
Ci proponiamo di creare un ambiente con il Web Server Apache-PHP, l’ RDBMS MySQL e l’interfaccia di gestione phpMyAdmin. Tutti servizi sono containerizzati attraverso Docker Compose
Vediamo inizialmente come creare un ambiente senza phpMyAdmin, ne testiamo il funzionamento e solo dopo integriamo il servizio phpMyAdmin nostro file docker-compose.yml
.
Vedremo come sarà semplice arricchire la nostra applicazione con UN SOLO COMANDO e SENZA INSTALLARE ALCUN SOFTWARE!
Step 1: Creazione di un ambiente di base con Apache-PHP e MySQL
Iniziamo creando un’applicazione con Apache, PHP e MySQL utilizzando Docker Compose. Creiamo una nuova directory (Apache-PHP-MySQL-phpMyAdmin) per il progetto e ci posizioniamo al suo interno.
Tasto destro del mouse -> Apri nel Terminale (si aprirà PowerShell) e scriviamo
code .
(Si aprirà Visual Studio Code nella cartella di progetto)

creiamo il file docker-compose.yml
con il seguente contenuto:
version: '3'
services:
web:
build: .
image: php:8.2-apache
container_name: apache_php
ports:
- "8080:80"
volumes:
- ./sorgenti:/var/www/html
networks:
- app-network
db:
image: mysql:8.0
container_name: mysql_db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
networks:
- app-network
networks:
app-network:
driver: bridge
Analizziamo il contenuto del file:
- La versione del file
docker-compose.yml
indica quale schema di configurazione viene utilizzato. In questo caso,version: '3'
è una delle versioni più comuni per Docker Compose e rappresenta una sintassi che è compatibile con Docker 1.13.0 e versioni successive. La versione 3 supporta la gestione di servizi, reti, volumi e altre risorse.
- Servizio
web
(Apache-PHP):- image: php:8.4.6-apache-bullseye: Questo campo definisce l’immagine Docker da usare per il servizio. In questo caso, l’immagine è basata su PHP 8.4.6 con Apache. Questa immagine è già preconfigurata per eseguire PHP con un server Apache.
-
build: .
consente di indicare a Docker che la costruzione dell’immagine deve partire da un Dockerfile anzichè dall’immagine originaria. Il Dockerfile ci consentirà di montare un nuovo layer sull’immagine originaria: l’estensione mysqli -
container_name: apache_php: Imposta un nome personalizzato per il contenitore, che in questo caso sarà
apache_php
. Questo nome può essere utilizzato per riferirsi al contenitore da altre parti del sistema, come per fermarlo o eseguire comandi specifici. -
ports: – “8080:80”: Mappa la porta 80 del contenitore (la porta predefinita di Apache) sulla porta 8080 della macchina host. Ciò significa che potremo accedere all’applicazione web tramite
http://localhost:8080
. -
volumes: – ./src:/var/www/html: Monta una cartella locale (
./sorgenti
) all’interno del contenitore nella directory/var/www/html
, che è la directory predefinita per i file web di Apache (per capire qual è la WORKDIR basta fare ildocker inspect
oppure direttamente nella documentazione dell’immagine da Docker Hub). In pratica, i file PHP che mettiamo nella cartella./sorgenti
sulla nostra macchina locale saranno visibili e accessibili all’interno del contenitore. -
networks: – app-network: Specifica che il servizio web sarà collegato alla rete
app-network
, che viene definita più in basso nel file. Questo permette al contenitoreweb
di comunicare con altri contenitori sulla stessa rete, come il contenitore del database MySQL.
- Servizio
db
(MySQL)- image: mysql:5.7: Specifica l’immagine Docker da usare per il servizio. In questo caso, si usa l’immagine ufficiale di MySQL 5.7. Questa immagine è preconfigurata per eseguire MySQL.
-
container_name: mysql_db: Imposta un nome personalizzato per il contenitore MySQL, che in questo caso sarà
mysql_db
. -
environment: La sezione
environment
definisce le variabili di ambiente da passare al contenitore MySQL. -
MYSQL_ROOT_PASSWORD: rootpassword: Nella documentazione dell’immagine di mysql è esplicitato che è NECESSARIO esplicitare il valore di questa variabile di ambiente. In questo caso il valore (quindi la password di root) è
root
. -
MYSQL_DATABASE: testdb: Crea un database chiamato
testdb
durante l’avvio del contenitore. Questo è utile per iniziare con un database già configurato. -
ports: – “3306:3306”: Mappa la porta 3306 del contenitore (la porta predefinita di MySQL) sulla porta 3306 della macchina host. Ciò significa che MySQL sarà accessibile sulla nostra macchina locale tramite
localhost:3306
. -
networks: – app-network: Specifica che il servizio MySQL sarà collegato alla rete
app-network
, permettendo la comunicazione con il contenitore Apache-PHP e altri contenitori sulla stessa rete.
- Reti
networks: La sezione networks
definisce le reti che i contenitori useranno per comunicare tra loro.
-
app-network: Questa è la rete personalizzata definita nel file. Viene creata per i contenitori
web
edb
, che possono quindi scambiarsi dati tramite questa rete privata.
-
driver: bridge: Il driver
bridge
è il driver predefinito per la rete, che consente ai contenitori di comunicare tra loro sulla stessa macchina host tramite una rete privata.
Step 2: Creazione del Dockerfile
All’interno della cartella di progetto creiamo il Dockerfile:
FROM php:8.2-apache
# Abilitare l'estensione mysqli
RUN docker-php-ext-install mysqli
# Impostare la directory di lavoro
WORKDIR /var/www/html
Non ci dilunghiamo nella spiegazione poichè la teoria (e la pratica) sul Dockerfile è stata spiegata nella guida: https://profgiagnotti.it/dockerfile-personalizzazione-di-immagini-e-push-su-docker-hub/
Step 3: Creazione della cartella sorgenti
per i file PHP
Creiamo la cartella sorgenti
all’interno della cartella del progetto e aggiungiamo un file PHP di esempio. All’interno di sorgenti
, creiamo un file chiamato index.php
:
<?php
$servername = "db";
$username = "root";
$password = "root";
$dbname = "testdb";
// Crea connessione
$conn = new mysqli($servername, $username, $password, $dbname);
// Verifica connessione
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
echo "Connessione a MySQL stabilita con successo!";
// Chiudi la connessione
$conn->close();
?>
Questo script PHP si connette al database MySQL e stampa un messaggio di successo se la connessione è riuscita.
Step 4: Avvio dell’applicazione
Ora che abbiamo creato la configurazione di Docker Compose e il nostro file PHP, possiamo avviare i servizi. Apri il terminale nella directory del progetto (o direttamente da Visual Studio Code) e lanciare il comando:
docker-compose up --build -d
Questo comando avvierà i container in background.

Al termine del processo di avvio possiamo verificare che i contenitori siano in esecuzione con: docker ps -a
oppure da Docker Desktop

Nota: Se si effettuano modifiche nel Dockerfile conviene vermare i container con:
docker compose down
e forzare la ricostruzione delle immagini con:
docker-compose up --build
Step 5: Testare il Funzionamento
Una volta che i container sono attivi, apriamo il browser e visitiamo http://localhost:8080
. Vediamo la pagina con il messaggio “Connessione a MySQL stabilita con successo!” che indica che la connessione al database MySQL è stata stabilita con successo.

Step 6: Aggiungere phpMyAdmin per la gestione del database
A questo punto, l’applicazione è funzionante con Apache-PHP e MySQL. Ora, aggiungiamo phpMyAdmin al file docker-compose.yml
per semplificare la gestione del database MySQL tramite una interfaccia web.
Aggiornare il file docker-compose.yml
aggiungendo il servizio phpmyadmin
come segue:
version: '3'
services:
web:
build: .
image: php:8.2-apache
container_name: apache_php
ports:
- "8080:80"
volumes:
- ./sorgenti:/var/www/html
networks:
- app-network
db:
image: mysql:8.0
container_name: mysql_db
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
ports:
- "3306:3306"
networks:
- app-network
phpmyadmin:
image: phpmyadmin
container_name: phpmyadmin
environment:
PMA_HOST: db
PMA_PORT: 3306
ports:
- "8081:80"
networks:
- app-network
networks:
app-network:
driver: bridge
- Servizio
phpmyadmin
- image: phpmyadmin: Specifica l’immagine Docker da usare per il servizio. In questo caso, si usa l’immagine ufficiale di phpmyadmin.
-
container_name: phpmyadmin: Imposta un nome personalizzato per il contenitore phpMyAdmin, che in questo caso sarà
phpmyadmin
. -
environment: La sezione
environment
definisce le variabili di ambiente da passare al contenitore phpmyadmin. -
PMA_HOST: db: Nella documentazione dell’immagine di phpmyadmin è esplicitato che è, per un uso con un DB server esterno, è NECESSARIO esplicitare il nome del DB esterno (nel nostro caso il servizio
db
di mysql) -
PMA_PORT: 3306: Nella documentazione dell’immagine di phpmyadmin è esplicitato che è, per un uso con un DB server esterno, è NECESSARIO esplicitare la porta che espone il servizio esterno (nel nostro caso la 3306
-
ports: – “8081:80”: Mappa la porta 80 del contenitore sulla porta 8081 della macchina host. Ciò significa che phpmyadmin sarà accessibile sulla nostra macchina locale tramite
localhost:8081
. -
networks: – app-network: Specifica che il servizio sarà collegato alla rete
app-network
, permettendo la comunicazione con il contenitore Apache-PHP e MySQL
Step 7: Rilanciare Docker Compose
Per aggiungere il nuovo servizio senza fermare gli altri, eseguire il seguente comando:
docker-compose up -d
Step 8: Testare phpMyAdmin
Ora, apriamo il browser e visitiamo http://localhost:8081
. Vediamo l’interfaccia di phpMyAdmin. Accediamo con le seguenti credenziali:
-
Username:
root
-
Password:
root (impostata in precedenza)
Possiamo ora gestire facilmente il database MySQL tramite l’interfaccia grafica di phpMyAdmin.

Test completo dell’applicazione
Proviamo ora a testare l’applicazione nel suo complesso:
creiamo un nuovo db da phpmyadmin “test_completo”, una nuova tabella “utenti” e lo popoliamo la tabella con 2 record

modifichiamo il nome di index.php in connessione.php e lo modifichiamo in questo modo: (sostituiamo il dbname ed eliminiamo il messaggio di successo)
<?php
$servername = "db";
$username = "root";
$password = "root";
$dbname = "test_completo";
// Crea connessione
$conn = new mysqli($servername, $username, $password, $dbname);
// Verifica connessione
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
Scriviamo il nuovo index.html come segue:
<?php
//includiamo la connessione al database
include 'connessione.php';
//selezioniamo gli utenti dalla tabella "utenti" del database "test_completo"
$sql = "SELECT * FROM utenti";
$result = $conn->query($sql);
//verifichiamo se ci sono risultati, estraiamo i dati e li visualizziamo in formato tabellare
if ($result->num_rows > 0) {
echo "<table border='1'><tr><th>ID</th><th>Cognome</th><th>Nome</th></tr>";
// output data of each row
while($row = $result->fetch_assoc()) {
echo "<tr><td>" . $row["id"]. "</td><td>" . $row["Cognome"]. "</td><td>" . $row["Nome"]. "</td></tr>";
}
echo "</table>";
} else {
echo "0 risultati";
}
$conn->close();
?>
Questo script seleziona i record di “utenti” e li visualizza in formato tabellare.
Non ci resta che tornare sul browser all’URL: localhot:8080, aggiornare e….

verificare che la nostra App funziona correttamente con semplici step e senza installare software aggiuntivo
Vantaggi di Docker Compose: Un Solo Comando per Ampliare l’Applicazione
L’aspetto più interessante di Docker Compose è la sua capacità di ampliare l’applicazione rapidamente con un solo comando. In pochi passaggi, abbiamo aggiunto un nuovo servizio (phpMyAdmin) al nostro ambiente, senza dover modificare manualmente configurazioni complesse o riavviare i contenitori precedenti.
Conclusione
In questo articolo, abbiamo creato un ambiente di sviluppo con Docker Compose utilizzando Apache-PHP e MySQL. Successivamente, abbiamo aggiunto phpMyAdmin per una gestione più semplice del database. Questo processo dimostra quanto sia facile estendere un’applicazione con Docker Compose, rendendo la gestione delle dipendenze e l’ampliamento dei servizi veloce e senza problemi.
Utilizzare Docker Compose permette di automatizzare la configurazione di ambienti complessi, risparmiando tempo e riducendo la possibilità di errori. Con un solo comando, è possibile lanciare, modificare e aggiornare intere applicazioni.
Lascia un commento