Docker Compose: gestire più container con un unico file di configurazione
Quando iniziamo a utilizzare Docker, avviare un container alla volta è semplice. Basta un comando per mettere in funzione un server web, provare un database o avviare un servizio di test.
Le cose cambiano quando un’applicazione ha bisogno di più componenti per funzionare. Un sito WordPress, per esempio, richiede un server applicativo e un database. Dobbiamo avviare entrambi, configurare la comunicazione tra loro e assicurarci che i dati importanti non vadano persi quando ricreiamo un container.
Possiamo gestire tutto manualmente, ma ricordare numerosi comandi e parametri diventa presto scomodo. Docker Compose ci permette di descrivere l’intera applicazione in un file di configurazione e di gestirla come un unico progetto.
Vediamo come funziona attraverso un esempio concreto, adatto anche a chi sta costruendo il proprio homelab Linux.
Che cos’è Docker Compose e perché è utile
Docker Compose è uno strumento che permette di definire e gestire applicazioni composte da più servizi Docker. Invece di avviare ogni container con un comando separato, descriviamo la configurazione in un file chiamato normalmente compose.yaml.
Nel file possiamo specificare quali immagini utilizzare, quali porte pubblicare, quali variabili d’ambiente impostare, quali volumi conservare e come collegare i servizi attraverso la rete.
Docker Compose legge questa configurazione e ci aiuta a creare, avviare, arrestare e aggiornare i componenti dell’applicazione.
Il vantaggio non è soltanto risparmiare tempo. La configurazione rimane scritta in un file leggibile, che possiamo modificare, conservare e riutilizzare. Se dobbiamo ricreare l’ambiente su un altro computer, abbiamo una descrizione molto più chiara di ciò che serve.
Se non abbiamo ancora familiarità con immagini e container, conviene partire dalla nostra guida introduttiva a Docker su Linux.
Prepariamo il progetto
Per la nostra prova utilizzeremo WordPress e MariaDB. Il primo servizio ospiterà il sito, mentre il secondo conserverà i dati del database.
Iniziamo creando una directory dedicata:
mkdir -p ~/docker-wordpress
cd ~/docker-wordpress
Entriamo così in una piccola cartella di progetto nella quale conserveremo il file di configurazione. In questo modo evitiamo di disperdere i file tra directory diverse e possiamo ritrovare facilmente tutto ciò che riguarda l’applicazione.
Prima di procedere, verifichiamo che Docker sia installato e che il nostro utente possa utilizzarlo. Possiamo controllare la versione con:
docker --version
docker compose version
Il secondo comando verifica la presenza del plugin Docker Compose. Se non è disponibile, dovremo installare o correggere la configurazione di Docker secondo le istruzioni adatte alla nostra distribuzione.
Il file compose.yaml: tutta l’applicazione in un solo posto
Nella directory del progetto creiamo il file:
nano compose.yaml
Inseriamo questa configurazione:
services:
db:
image: mariadb:11
restart: unless-stopped
environment:
MARIADB_DATABASE: wordpress
MARIADB_USER: wpuser
MARIADB_PASSWORD: cambia-questa-password
MARIADB_ROOT_PASSWORD: cambia-anche-questa-password
volumes:
- db_data:/var/lib/mysql
wordpress:
image: wordpress:latest
restart: unless-stopped
depends_on:
- db
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: cambia-questa-password
ports:
- "127.0.0.1:8080:80"
volumes:
- wordpress_data:/var/www/html
volumes:
db_data:
wordpress_data:
Prima di avviare il progetto, sostituiamo le password di esempio con valori robusti e coerenti: la password del database indicata nel servizio WordPress deve corrispondere a quella assegnata all’utente MariaDB.
Queste credenziali sono inserite direttamente nel file per mantenere l’esempio semplice. Per un progetto reale è preferibile gestire i segreti con maggiore attenzione, evitando di pubblicarli in repository o condividerli accidentalmente.
Vediamo ora i punti più importanti della configurazione.
I servizi sono i componenti dell’applicazione
La sezione services definisce due servizi: db e wordpress.
Il servizio db utilizza l’immagine MariaDB e prepara un database chiamato wordpress, insieme a un utente dedicato all’applicazione. Il servizio wordpress, invece, utilizza l’immagine ufficiale di WordPress e riceve i parametri necessari per collegarsi al database.
La voce WORDPRESS_DB_HOST: db:3306 merita particolare attenzione. Il nome db corrisponde al nome del servizio definito nel file Compose. Nella rete creata per il progetto, Docker permette ai servizi di raggiungersi attraverso i rispettivi nomi, senza che dobbiamo fissare manualmente gli indirizzi IP dei container.
Non abbiamo quindi bisogno di pubblicare la porta del database sul computer: WordPress può raggiungerlo direttamente attraverso la rete interna del progetto.
Le porte decidono da dove possiamo raggiungere WordPress
La riga:
ports:
- "127.0.0.1:8080:80"
collega la porta 8080 del nostro computer alla porta 80 del container WordPress, limitando la pubblicazione all’indirizzo locale 127.0.0.1.
Questo significa che, sullo stesso computer, potremo aprire il sito nel browser all’indirizzo http://localhost:8080. Non stiamo invece configurando l’accesso diretto da altri dispositivi della rete locale.
È una scelta prudente per un ambiente di prova: prima di rendere un servizio raggiungibile dalla rete o da Internet, dobbiamo valutare le regole di accesso, gli aggiornamenti e la sicurezza della configurazione.
I volumi conservano i dati
Nel file troviamo anche due volumi nominati:
volumes:
db_data:
wordpress_data:
Il primo conserva i dati del database; il secondo conserva i file di WordPress. I volumi vengono collegati ai rispettivi percorsi all’interno dei container.
Questo dettaglio è fondamentale. Un container può essere rimosso e ricreato, mentre i dati conservati in un volume possono continuare a esistere. Non dobbiamo quindi confondere la durata del container con quella dei dati.
I volumi, però, non sono un sistema di backup: se i dati sono importanti, dovremo predisporre anche copie di sicurezza adeguate. Per approfondire, possiamo leggere la nostra guida ai volumi Docker e alla persistenza dei dati.
Che cosa significa depends_on
La voce depends_on indica che Compose deve avviare il servizio db prima di quello WordPress. Non garantisce, da sola, che il database abbia già completato l’inizializzazione e sia pronto ad accettare connessioni.
È una distinzione utile da conoscere: l’ordine di avvio e la reale disponibilità di un servizio non sono la stessa cosa. In applicazioni più complesse possiamo aggiungere controlli di salute e condizioni appropriate per coordinare meglio i componenti.
Avviamo l’applicazione con Docker Compose
Una volta salvato il file, restiamo nella directory docker-wordpress e avviamo il progetto:
docker compose up -d
Compose legge compose.yaml, recupera le immagini necessarie se non sono già presenti, crea le risorse richieste e avvia i servizi in background. L’opzione -d ci permette di tornare al terminale senza mantenere il comando collegato ai log.
Per controllare lo stato dei servizi utilizziamo:
docker compose ps
Possiamo poi consultare i messaggi prodotti dai container:
docker compose logs
Se vogliamo seguire i log mentre arrivano nuovi messaggi, aggiungiamo -f:
docker compose logs -f
Per interrompere la visualizzazione dei log premiamo Ctrl+C. In questo caso interrompiamo il comando di osservazione, non necessariamente i servizi in esecuzione.
Se tutto è partito correttamente, apriamo il browser sullo stesso computer e visitiamo:
http://localhost:8080
WordPress dovrebbe mostrarci la schermata iniziale di configurazione. Da qui possiamo completare l’installazione del sito di prova.
Se la pagina non compare, non è necessario ricominciare da zero: controlliamo prima docker compose ps e i log, per capire quale servizio non sta funzionando come previsto.
Fermare e riavviare il progetto
Uno dei vantaggi di Compose è che possiamo eseguire le operazioni principali dalla stessa directory.
Per fermare i servizi senza rimuovere il progetto utilizziamo:
docker compose stop
Per avviarli nuovamente:
docker compose start
Quando invece vogliamo arrestare e rimuovere i container e le reti create dal progetto, utilizziamo:
docker compose down
Attenzione: il comando down, in questa configurazione, non elimina i volumi nominati. I dati del database e i file persistenti possono quindi essere riutilizzati al successivo avvio. Non è comunque un sostituto di un backup.
Esiste anche l’opzione -v, che rimuove i volumi nominati associati al progetto:
docker compose down -v
Usiamola soltanto quando siamo davvero sicuri di voler eliminare anche quei dati. In un sito che contiene informazioni importanti, una distrazione può avere conseguenze molto più serie del semplice arresto di un container.
Perché Compose è particolarmente utile in un homelab
Con Docker Compose abbiamo trasformato due container distinti in un progetto descritto da un unico file. La configurazione ci dice quali servizi esistono, come comunicano, quali porte sono pubblicate e dove vengono conservati i dati.
Questo approccio diventa ancora più utile quando aggiungiamo altri componenti: un reverse proxy, un sistema di monitoraggio, una cache o altri servizi. Possiamo mantenere ogni progetto nella propria directory e documentarne la configurazione senza dover ricordare una lunga sequenza di comandi.
È importante ricordare, però, che Compose non sostituisce la comprensione delle reti Docker. Quando un servizio non riesce a raggiungerne un altro, dobbiamo comunque sapere quali componenti comunicano tra loro e quali porte sono effettivamente necessarie. Per questo può essere utile riprendere la nostra guida su Docker Networking.
Conclusioni
Docker Compose ci permette di descrivere un’applicazione composta da più container attraverso un file di configurazione semplice da conservare e modificare. Con il nostro esempio abbiamo messo in relazione WordPress e MariaDB, pubblicato il servizio web soltanto in locale e utilizzato volumi per conservare i dati.
Il passaggio importante non è soltanto imparare docker compose up -d. È iniziare a pensare ai container come componenti di un progetto: ciascuno ha un ruolo, una configurazione e un modo preciso di comunicare con gli altri.
Per chi sta costruendo un homelab Linux, questa è una base concreta da cui partire. Possiamo aggiungere un servizio alla volta, capire come interagiscono e migliorare la configurazione man mano che le nostre esigenze crescono.
LICENZA E CONDIZIONI D’USO
Questo How-to è rilasciato sotto licenza Creative Commons Attribution-NonCommercial 3.0 Italy.
CONTATTI DELL’AUTORE
Marco Ciammella marco@orvietolinux.it
Orvieto Linux User Group info@orvietolinux.it