Ricerca nel sito web

Come installare e usare Docker Compose su Ubuntu


Introduzione

Docker semplifica il processo di gestione dei processi applicativi nei container. Sebbene i container siano simili alle macchine virtuali in alcuni aspetti, sono più leggeri e meno esigenti in termini di risorse. Questo permette agli sviluppatori di suddividere un ambiente applicativo in più servizi isolati.

Per le applicazioni che dipendono da diversi servizi, orchestrare tutti i container affinché si avviino, comunichino e si spengano insieme può diventare rapidamente complicato. Docker Compose è uno strumento che consente di eseguire ambienti applicativi multi-container basati su definizioni impostate in un file YAML. Utilizza le definizioni dei servizi per costruire ambienti completamente personalizzabili con più container che possono condividere reti e volumi di dati.

Questa guida ti accompagnerà nell'installazione di Docker Compose su un server Ubuntu e nell'esecuzione di un semplice container. Da lì, imparerai a costruire un ambiente multi-servizio utilizzando un'applicazione WordPress e un database MySQL. Tratteremo anche argomenti più avanzati, tra cui il dimensionamento dei servizi, la definizione di reti personalizzate e l'utilizzo di direttive modulari di inclusione. Infine, questo articolo fornisce una guida alla migrazione dall'antico docker-compose (v1) al moderno docker compose (v2) e una sezione dettagliata sulla risoluzione dei problemi comuni come conflitti di porte e errori di autorizzazione.

Punti Chiave:

  • Docker Compose è uno strumento per definire ed eseguire applicazioni multi-container utilizzando un unico file YAML per configurare servizi, reti e volumi.
  • Docker Compose è installato su Ubuntu aggiungendo il repository ufficiale di Docker e utilizzando apt per installare il pacchetto docker-compose-plugin.
  • Il comando moderno è docker compose (con uno spazio). Questo sostituisce lo strumento v1 deprecato docker-compose (con un trattino).
  • Usa docker compose up -d per avviare un'applicazione in modalità distaccata e docker compose down per fermare e rimuovere tutti i suoi container e le reti.
  • La direttiva depends_on aiuta a controllare l'ordine di avvio dei servizi, ad esempio garantendo che un contenitore del database si avvii prima di un contenitore dell'applicazione web.
  • I problemi più frequenti sono "Permesso Negato" (risolto aggiungendo il tuo utente al gruppo docker), conflitti di porta (risolti cambiando la porta dell'host nel file YAML) ed errori di sintassi YAML (risolti correggendo l'indentazione).
  • Puoi eseguire più istanze di un servizio utilizzando il comando docker compose up --scale <service_name>=<number>.
  • La direttiva include ti permette di suddividere un grande file docker-compose.yml in file di configurazione più piccoli e gestibili.

Prerequisiti

Per seguire questo articolo, avrai bisogno di:

  • Accesso a una macchina locale Ubuntu o a un server di sviluppo come utente non root con privilegi sudo. Se stai usando un server remoto, è consigliabile avere un firewall attivo installato. Per configurare questi elementi, consulta la nostra Guida alla Configurazione Iniziale del Server per Ubuntu.
  • Docker installato sul tuo server o sulla tua macchina locale, seguendo i passaggi 1 e 2 della guida Come installare Docker su Ubuntu - Guida passo passo.

Nota: A partire da Docker Compose v2, Docker ha iniziato a utilizzare il comando plugin CLI compose, abbandonando il vecchio docker-compose come documentato nella nostra guida Come Installare Docker Compose su Ubuntu (Guida Passo-Passo). Sebbene l'installazione sia diversa, in generale l'uso effettivo consiste nel rimuovere il trattino dalle chiamate docker-compose, trasformandole in docker compose. Per i dettagli completi sulla compatibilità, consulta la documentazione ufficiale di Docker sulla compatibilità dei comandi tra il nuovo compose e il vecchio docker-compose.

Passo 1 — Installazione di Docker Compose

Ci sono due modi per installare Docker Compose su Ubuntu:

  • Installa utilizzando il repository
  • Installa manualmente

Discuteremo entrambi i modi in questa sezione.

Installare Docker Compose usando il repository apt

Per prima cosa, configuriamo il repository apt di Docker.

# Add Docker's official GPG key:

sudo apt-get update

sudo apt-get install ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings

sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

sudo chmod a+r /etc/apt/keyrings/docker.asc



# Add the repository to Apt sources:

echo \

  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \

  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \

  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

Ora, puoi installare Docker Compose utilizzando il seguente comando:

sudo apt install docker-compose-plugin

Docker Compose è ora installato correttamente sul tuo sistema. Per verificare che l'installazione sia avvenuta con successo, puoi eseguire:

docker compose version

Vedrai un output simile a questo:

Docker Compose version v2.3.3

Installazione manuale di Docker Compose

Per assicurarti di ottenere la versione stabile più aggiornata di Docker Compose, scaricherai questo software dal suo repository ufficiale su GitHub.

Per prima cosa, conferma l'ultima versione disponibile nella loro pagina dei rilasci. Al momento della scrittura, la versione stabile più recente è v2.40.2.

Usa il seguente comando per scaricare:

mkdir -p ~/.docker/cli-plugins/

curl -SL https://github.com/docker/compose/releases/download/v2.40.2/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose

Successivamente, imposta i permessi corretti in modo che il comando docker compose sia eseguibile:

chmod +x ~/.docker/cli-plugins/docker-compose

Nella sezione successiva, vedrai come configurare un file docker-compose.yml e far partire un ambiente containerizzato con questo strumento.

Passo 2 — Configurazione di un file docker-compose.yml

Per dimostrare come configurare un file docker-compose.yml e lavorare con Docker Compose, creerai un ambiente server web utilizzando l'immagine ufficiale di Nginx presente su Docker Hub, il registro pubblico di Docker. Questo ambiente containerizzato fornirà un singolo file HTML statico.

Inizia creando una nuova directory nella tua cartella home, e poi spostati al suo interno:

mkdir ~/compose-demo

cd ~/compose-demo

In questa directory, crea una cartella per l'applicazione che fungerà da root dei documenti per il tuo ambiente Nginx:

mkdir app

Usando il tuo editor di testo preferito, crea un nuovo file index.html all'interno della cartella app:

nano app/index.html

Inserisci il seguente contenuto in questo file:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Docker Compose Demo</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
</head>
<body>

    <h1>This is a Docker Compose Demo Page.</h1>
    <p>This content is being served by an Nginx container.</p>

</body>
</html>

Salva e chiudi il file quando hai finito. Se stai usando nano, puoi farlo digitando CTRL+X, poi Y e INVIO per confermare.

Successivamente, crea il file docker-compose.yml:

nano docker-compose.yml

Inserisci il seguente contenuto nel tuo file docker-compose.yml:

services:
  web:
    image: nginx:alpine
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/share/nginx/html

Nell'attuale Docker Compose, il campo version è opzionale e spesso viene omesso, poiché Compose può rilevare automaticamente la versione della configurazione. L'esempio sopra non include un campo version, che è l'approccio consigliato per la maggior parte dei nuovi progetti. È necessario specificare version solo per la compatibilità con versioni precedenti.

Hai poi il blocco services, dove configuri i servizi che fanno parte di questo ambiente. Nel tuo caso, hai un unico servizio chiamato web. Questo servizio utilizza l'immagine nginx:alpine e imposta un reindirizzamento delle porte con la direttiva ports. Tutte le richieste sulla porta 8000 della macchina host (il sistema da cui stai eseguendo Docker Compose) saranno reindirizzate al container web sulla porta 80, dove Nginx sarà in esecuzione.

La direttiva volumes creerà un volume condiviso tra la macchina host e il container. Questo condividerà la cartella locale app con il container, e il volume sarà situato in /usr/share/nginx/html all'interno del container, sovrascrivendo così la root documenti predefinita per Nginx.

Salva e chiudi il file.

Hai creato una pagina demo e un file docker-compose.yml per creare un ambiente server web containerizzato che la ospiterà. Nel passaggio successivo, avvierai questo ambiente con Docker Compose.

Fase 3 — Esecuzione di Docker Compose

Con il file docker-compose.yml al suo posto, puoi ora eseguire Docker Compose per avviare il tuo ambiente. Il seguente comando scaricherà le immagini Docker necessarie, creerà un container per il servizio web e avvierà l'ambiente containerizzato in modalità background:

docker compose up -d

Docker Compose cercherà prima l'immagine definita sul tuo sistema locale e, se non riesce a trovarla, scaricherà l'immagine da Docker Hub. Vedrai un output simile a questo:

Creating network "compose-demo_default" with the default driver
Pulling web (nginx:alpine)...
alpine: Pulling from library/nginx
cbdbe7a5bc2a: Pull complete
10c113fb0c77: Pull complete
9ba64393807b: Pull complete
c829a9c40ab2: Pull complete
61d685417b2f: Pull complete
Digest: sha256:57254039c6313fe8c53f1acbf15657ec9616a813397b74b063e32443427c5502
Status: Downloaded newer image for nginx:alpine
Creating compose-demo_web_1 ... done

Nota: Se si verifica un errore “permesso negato” durante l'esecuzione di docker compose up, questo di solito significa che il tuo utente non root non ha l'autorizzazione per accedere al socket del demone Docker.

Per impostazione predefinita, il demone Docker si collega a un socket Unix (/var/run/docker.sock) che è di proprietà dell'utente root. Per risolvere questo problema, è necessario aggiungere il proprio utente non-root al gruppo docker, che viene creato durante l'installazione di Docker.

Esegui il seguente comando per aggiungere il tuo utente al gruppo docker:

sudo usermod -aG docker ${USER}

Dopo aver eseguito questo comando, sarà necessario disconnettersi e riconnettersi affinché le modifiche al gruppo abbiano effetto. Puoi anche attivare le modifiche per la sessione del terminale corrente digitando:

newgrp docker

Questo comando dovrebbe risolvere eventuali errori di autorizzazione relativi al socket Docker. Per una guida completa, si prega di fare riferimento al Passo 2 di Come Installare Docker su Ubuntu – Guida Passo-Passo.

Il tuo ambiente è ora attivo e funzionante in background. Per verificare che il contenitore sia attivo, puoi eseguire:

docker compose ps

Questo comando ti mostrerà informazioni sui container in esecuzione e sul loro stato, così come eventuali reindirizzamenti di porte attualmente in atto:

       Name                     Command               State          Ports        
----------------------------------------------------------------------------------
compose-demo_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8000->80/tcp

Ora puoi accedere all'applicazione demo puntando il tuo browser a localhost:8000 se stai eseguendo questa demo sulla tua macchina locale, oppure a il_tuo_dominio_o_IP_del_server:8000 se stai eseguendo questa demo su un server remoto.

Vedrai una pagina come questa:

Il volume condiviso che hai configurato all'interno del file docker-compose.yml mantiene i file della cartella app sincronizzati con la root dei documenti del container. Se apporti modifiche al file index.html, queste verranno automaticamente rilevate dal container e quindi riflesse nel tuo browser quando ricarichi la pagina.

Nel passaggio successivo, vedrai come gestire il tuo ambiente containerizzato con i comandi di Docker Compose.

Fase 4 — Familiarizzare con i comandi di Docker Compose

Hai visto come configurare un file docker-compose.yml e avviare il tuo ambiente con docker compose up. Ora vedrai come usare i comandi di Docker Compose per gestire e interagire con il tuo ambiente containerizzato.

Per controllare i log prodotti dal tuo container Nginx, puoi usare il comando logs:

docker compose logs

Vedrai un output simile a questo:

Attaching to compose-demo_web_1
web_1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_1  | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
web_1  | 10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_1  | /docker-entrypoint.sh: Configuration complete; ready for start up
web_1  | 172.22.0.1 - - [02/Jun/2020:10:47:13 +0000] "GET / HTTP/1.1" 200 353 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36" "-"

Se vuoi mettere in pausa l'esecuzione dell'ambiente senza modificare lo stato attuale dei tuoi container, puoi usare:

docker compose pause
Pausing compose-demo_web_1 ... done

Per riprendere l'esecuzione dopo aver messo in pausa:

docker compose unpause
Unpausing compose-demo_web_1 ... done

Il comando stop terminerà l'esecuzione del container, ma non distruggerà alcun dato associato ai tuoi container:

docker compose stop
Stopping compose-demo_web_1 ... done

Se vuoi rimuovere i container, le reti e i volumi associati a questo ambiente containerizzato, usa il comando down:

docker compose down
Removing compose-demo_web_1 ... done
Removing network compose-demo_default

Nota che questo non rimuoverà l'immagine di base utilizzata da Docker Compose per avviare il tuo ambiente (nel tuo caso, nginx:alpine). In questo modo, ogni volta che riavvierai il tuo ambiente con un docker compose up, il processo sarà molto più veloce poiché l'immagine è già presente nel tuo sistema.

Nel caso volessi anche rimuovere l'immagine di base dal tuo sistema, puoi usare:

docker image rm nginx:alpine
Untagged: nginx:alpine
Untagged: nginx@sha256:b89a6ccbda39576ad23fd079978c967cecc6b170db6e7ff8a769bf2259a71912
Deleted: sha256:7d0cdcc60a96a5124763fddf5d534d058ad7d0d8d4c3b8be2aefedf4267d0270
Deleted: sha256:05a0eaca15d731e0029a7604ef54f0dda3b736d4e987e6ac87b91ac7aac03ab1
Deleted: sha256:c6bbc4bdac396583641cb44cd35126b2c195be8fe1ac5e6c577c14752bbe9157
Deleted: sha256:35789b1e1a362b0da8392ca7d5759ef08b9a6b7141cc1521570f984dc7905eb6
Deleted: sha256:a3efaa65ec344c882fe5d543a392a54c4ceacd1efd91662d06964211b1be4c08
Deleted: sha256:3e207b409db364b595ba862cdc12be96dcdad8e36c59a03b7b3b61c946a5741a

Nota: Consultare la nostra guida su Come installare Docker su Ubuntu – Guida passo passo per un riferimento più dettagliato sui comandi Docker.

Passo 5 — Creare un'applicazione multi-servizio

Il vero potere di Docker Compose risiede nella gestione di più servizi che lavorano insieme. L'esempio di Nginx era un servizio singolo. Creiamo un'applicazione più pratica e multi-servizio: un sito WordPress collegato a un database MySQL.

Questa configurazione prevede due servizi: wordpress (che esegue l'applicazione) e db (che esegue il database). Utilizzeremo anche i volumi Docker per garantire che i dati del database persistano anche se il container viene rimosso.

Creiamo una nuova directory per questa applicazione:

mkdir -p ~/compose-demo/wordpressapp

cd ~/compose-demo/wordpressapp

Per questo esempio, non abbiamo bisogno di file locali, poiché le immagini conterranno tutto il software necessario.

Crea un nuovo file docker-compose.yml:

nano docker-compose.yml

Incolla la seguente configurazione. Questo file è più complesso, quindi esamineremo ogni parte.

services:
  db:
    image: mysql:8.0
    container_name: mysql_db
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: <^your_root_password_here<^>
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: <^your_wordpress_password_here<^>
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    container_name: wordpress_app
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: <^your_wordpress_password_here<^>
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./wp_content:/var/www/html/wp-content
    depends_on:
      - db
    restart: unless-stopped

volumes:
  db_data:

Nota: Abbiamo inserito i valori della password direttamente nel codice a scopo illustrativo. Quando lo si utilizza in un ambiente reale, assicurati di usare le variabili d'ambiente nel file .env per evitare di esporre le tue credenziali.

Salva e chiudi il file. Ricorda di sostituire i segnaposto <^...^> con password forti e sicure.

Analizziamo le nuove direttive in questo file:

  • services: Questo blocco definisce ancora i nostri container. Ora ne abbiamo due: db e wordpress.
  • image: Stiamo usando mysql:8.0 per il database e l'immagine wordpress:latest per l'applicazione.
  • container_name: Imposta un nome specifico e leggibile dall'uomo per il container, che è più facile da riferire rispetto a quelli generati automaticamente.
  • environment: Questa è una lista di variabili d'ambiente passate al container. L'immagine mysql le usa per impostare la password di root e creare un database iniziale e un utente. L'immagine wordpress le usa per sapere come connettersi al suo database.
  • volumi (a livello di servizio):

    • Per il servizio db, db_data:/var/lib/mysql mappa un volume gestito da Docker chiamato db_data alla directory dei dati MySQL all'interno del container. Questo mantiene i tuoi dati al sicuro.
    • Per il servizio wordpress, ./wp_content:/var/www/html/wp-content mappa una directory locale (wp_content) alla directory dei contenuti di WordPress. Questo ti permette di modificare direttamente temi e plugin dalla tua macchina host.
  • depends_on: Questo indica a Compose di avviare il servizio db prima di avviare il servizio wordpress. Questo è importante, poiché WordPress non funzionerà se non trova il suo database all'avvio.
  • volumes (livello superiore): Questo blocco definisce i volumi nominati. db_data: crea un volume gestito da Docker, che è il modo preferito per gestire i dati persistenti.

Ora, avvia questa applicazione multi-servizio:

docker compose up -d

Compose scaricherà sia le immagini mysql che wordpress e poi creerà i container, avviando prima il servizio db.

Creating network "compose-demo_default" with the default driver
Creating volume "compose-demo_db_data" with default driver
Pulling db (mysql:8.0)...
...
Pulling wordpress (wordpress:latest)...
...
Creating mysql_db        ... done
Creating wordpress_app ... done

Ora puoi accedere al tuo nuovo sito WordPress navigando su localhost:8001 o <^il_tuo_dominio_o_IP_del_server<^>:8001 nel tuo browser. Dovresti vedere la schermata di installazione di WordPress. Per un esempio più dettagliato, consulta il nostro articolo su Come Installare WordPress con Docker Compose

Passo 6 — Utilizzare Docker Compose per lo sviluppo AI/ML

Oltre alle applicazioni web, Docker Compose è uno strumento estremamente utile per creare ambienti di data science e machine learning (AI/ML) riproducibili. I progetti AI/ML sono noti per le loro dipendenze complesse, inclusi specifiche versioni di Python, librerie come TensorFlow o PyTorch e driver di sistema come l'NVIDIA CUDA Toolkit. Docker Compose cattura l'intero ambiente in file di configurazione, risolvendo il problema del "funziona sul mio computer", che è cruciale per la ricerca riproducibile.

In questo esempio, creerai un ambiente AI/ML multi-servizio composto da:

  • JupyterLab: Un contenitore per lo sviluppo interattivo, costruito a partire da un Dockerfile personalizzato.
  • PostgreSQL: Un contenitore di database per memorizzare i risultati degli esperimenti e i metadati.
  • Accesso alla GPU: Il contenitore JupyterLab sarà configurato per accedere alla GPU NVIDIA del computer host, un requisito comune per l’addestramento dei modelli.

Prerequisito: Questo esempio richiede una GPU NVIDIA sul tuo computer e l'installazione del NVIDIA Container Toolkit. Senza di essi, il container non si avvierà quando si richiedono risorse GPU.

Struttura dei file

Per prima cosa, crea una directory per il tuo progetto. Al suo interno, creerai un file docker-compose.yml, una directory jupyter, un Dockerfile per Jupyter e un file requirements.txt. La struttura dovrebbe avere un aspetto simile a questo:

ai-project/
├── docker-compose.yml
└── jupyter/
    ├── Dockerfile
    └── requirements.txt

Creazione dei file del componente

1. Il file requirements.txt

Questo file elenca i pacchetti Python per il tuo ambiente di data science.

nano jupyter/requirements.txt

Aggiungi i pacchetti necessari. Per questo esempio, includeremo librerie per la manipolazione dei dati, la connessione al database e un framework di deep learning.

pandas
scikit-learn
tensorflow
jupyterlab
psycopg2-binary

Salva e chiudi il file.

2. Il Dockerfile

Questo file definisce il tuo servizio personalizzato di JupyterLab. Utilizza un'immagine ufficiale di Jupyter come base e installa i pacchetti da requirements.txt.

nano jupyter/Dockerfile

Incolla il seguente contenuto:

# Start from a base image that includes Jupyter and scientific libraries
FROM jupyter/scipy-notebook:latest

# Copy our local requirements file into the container
COPY requirements.txt /tmp/requirements.txt

# Install the Python packages
RUN pip install --no-cache-dir -r /tmp/requirements.txt

Questo file istruisce Docker a usare jupyter/scipy-notebook come punto di partenza, copiare il tuo requirements.txt nel container e poi usare pip per installare i pacchetti.

Definire l'ambiente con docker-compose.yml

Ora, crea il file principale docker-compose.yml. Questo file orchestrerà sia il servizio db che il tuo servizio personalizzato jupyter.

nano docker-compose.yml

Incolla la seguente configurazione, sostituendo i segnaposto <^...^> con le tue credenziali sicure.

services:
  db:
    image: postgres:15-alpine
    container_name: ai_postgres_db
    environment:
      POSTGRES_USER: <^your_db_user^>
      POSTGRES_PASSWORD: <^your_db_pass^>
      POSTGRES_DB: experiments
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U <^your_db_user^> -d experiments"]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped
    networks:
      - ai_net

  jupyter:
    build: ./jupyter
    container_name: ai_jupyter_lab
    ports:
      - "8888:8888"
    volumes:
      - ./notebooks:/home/jovyan/work
    environment:
      - POSTGRES_HOST=db
      - POSTGRES_USER=<^your_db_user^>
      - POSTGRES_PASSWORD=<^your_db_pass^>
      - POSTGRES_DB=experiments
    restart: unless-stopped
    networks:
      - ai_net
    depends_on:
      db:
        condition: service_healthy
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

volumes:
  postgres_data:
    name: ai_project_data

networks:
  ai_net:
    driver: bridge

Questo file di configurazione introduce diversi concetti importanti:

  • build: ./jupyter: Questo indica a Docker Compose di creare un'immagine personalizzata per il servizio jupyter. Cerca un Dockerfile all'interno della directory specificata ./jupyter.
  • volumes: - ./notebooks:/home/jovyan/work: Questo collega una directory locale chiamata notebooks al container. Questo garantisce che tutti i notebook Jupyter che crei vengano salvati direttamente sul tuo computer, persistendo anche dopo la rimozione del container.
  • healthcheck: Come visto nella sezione di risoluzione dei problemi, questo controllo verifica che il servizio db non sia solo in esecuzione, ma pronto a ricevere connessioni prima che altri servizi vengano avviati.
  • depends_on: ... condition: service_healthy: Questo indica al servizio jupyter di aspettare fino a quando il controllo di integrità del db non è passato prima di avviarsi.
  • deploy.resources.reservations.devices: Questo è il blocco che richiede l'accesso alla GPU.

    • driver: nvidia: Specifica il driver host da utilizzare.
    • count: 1: Richiede una GPU.
    • capabilities: [gpu]: Garantisce che il container abbia le capacità necessarie per utilizzare la GPU.

Eseguire l'ambiente AI/ML

Con i tuoi file al loro posto, sei pronto per costruire ed eseguire i servizi.

  1. Dalla tua directory ai-project, esegui il comando docker compose up. Devi aggiungere il flag --build la prima volta per dire a Compose di creare la tua immagine personalizzata di jupyter.

    docker compose up -d --build
  2. Compose prima costruirà l'immagine jupyter (il che può richiedere alcuni minuti mentre scarica TensorFlow), poi scaricherà l'immagine postgres, e infine avvierà entrambi i container.

    [+] Building 5.8s (9/9) FINISHED
     => [internal] load build definition from Dockerfile
    ...
    [+] Running 3/3
     ✔ Network ai-project_ai_net        Created
     ✔ Container ai_postgres_db         Started
     ✔ Container ai_jupyter_lab         Started
  3. Ora puoi accedere all'interfaccia di JupyterLab navigando su http://localhost:8888 (o <^il_tuo_indirizzo_ip_server^>:8888) nel tuo browser. Ti verrà richiesto un token, che puoi ottenere dai log del container:

    docker compose logs jupyter

    Cerca una riga simile a http://127.0.0.1:8888/lab?token=a1b2c3d4e5f6...

  4. All'interno di un notebook Jupyter, puoi ora connetterti al tuo database utilizzando il nome host db e le credenziali fornite. Il tuo ambiente ha anche accesso alla GPU dell'host per l'addestramento dei modelli.

Scalare i servizi e utilizzare reti personalizzate

Docker Compose include funzionalità per scalare i servizi e gestire le reti su cui comunicano.

Scalabilità del servizio con repliche

Immagina che il tuo server web Nginx del Passo 2 stia ricevendo troppo traffico. Puoi scalare il servizio web per eseguire più istanze del contenitore. Docker Compose può gestire questo automaticamente.

Ci sono due modi principali per scalare un servizio.

1. Utilizzo della chiave replicas (Preferito in v2)

Puoi definire il numero desiderato di istanze direttamente nel tuo file docker-compose.yml utilizzando le chiavi deploy e replicas. Questa funzione faceva originariamente parte di Docker Swarm, ma ora è disponibile anche per le distribuzioni standard di Compose.

Modifica il tuo docker-compose.yml di Nginx dal Passo 2:

services:
  web:
    image: nginx:alpine
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/share/nginx/html
    deploy:
      replicas: 3

Quando esegui docker compose up -d, Compose creerà tre container web. Tuttavia, avrai un problema: tutti e tre cercheranno di legarsi alla porta dell'host 8000. Questo causerà un errore “porta già allocata” per il secondo e il terzo container. Per risolvere questo problema in un ambiente di produzione, dovresti rimuovere la mappatura ports dal servizio web. In questo modo, i container web saranno accessibili solo all'interno della rete Docker. Un servizio bilanciatore di carico separato sarebbe l'unico con una porta pubblica. Esso distribuirebbe quindi il traffico alle tre repliche web.

Un esempio di configurazione potrebbe apparire così (questo è un esempio avanzato):

services:
  web:
    image: nginx:alpine
    # No 'ports' mapping here.
    # The service is only accessible inside the 'web-net' network.
    volumes:
      - ./app:/usr/share/nginx/html
    deploy:
      replicas: 3
    networks:
      - web-net

  load_balancer:
    image: nginx:latest
    ports:
      - "80:80" # The load_balancer is the only service with a public port.
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf # A config file that load balances to 'web'.
    networks:
      - web-net
    depends_on:
      - web

networks:
  web-net:

In questa configurazione, il load_balancer ascolta sulla porta 80 e instrada le richieste a web_1, web_2 e web_3 internamente.

Questa chiave replicas è più utile se usata con un reverse proxy (come Traefik o un'altra istanza di Nginx) che può bilanciare il carico delle richieste tra le repliche all'interno della rete Docker, senza che ogni replica debba esporre una porta sull'host.

2. Utilizzo del flag --scale

Un metodo comune per il ridimensionamento è il flag --scale, un retaggio di Compose v1. Questo flag viene applicato durante l'esecuzione e sovrascrive qualsiasi chiave replicas.

Tuttavia, devi fare attenzione alle definizioni delle porte. Se il tuo servizio definisce un mapping della porta host fisso (ad esempio, "8000:80"), eseguire docker compose up --scale causerà un errore per il secondo e il terzo container poiché tutti cercheranno di collegarsi alla stessa porta host.

Per utilizzare --scale con servizi che espongono porte, non devi usare una mappatura di porta host fissa.

  • Opzione 1: Mappare le porte dell'host in modo casuale (Buono per lo sviluppo)

    Puoi modificare il tuo docker-compose.yml per specificare solo la porta del container. Questo dice a Docker di mappare la porta 80 di ciascun container a una porta casuale disponibile sulla tua macchina host.

    services:
      web:
        image: nginx:alpine
        ports:
          - "80" # No fixed host port
        volumes:
          - ./app:/usr/share/nginx/html

    Ora, quando esegui il comando scale:

    docker compose up -d --scale web=3

    Esegui docker compose ps per vedere il risultato. Ogni container sarà in esecuzione su una porta host diversa, assegnata casualmente:

          Name                     Command               State          Ports        
    ----------------------------------------------------------------------------------
    compose-demo_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49154->80/tcp
    compose-demo-web_2   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49155->80/tcp
    compose-demo-web_3   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:49156->80/tcp
  • docker-compose.yml - Corretto per --scale

  • Opzione 2: Utilizzare un Reverse Proxy (Ideale per la Produzione)

    L'altra soluzione, come menzionato nella sezione replicas, è rimuovere completamente la direttiva ports dal servizio web. Si utilizzerebbe quindi un contenitore separato per il bilanciatore di carico (che ha l'unica porta pubblica) per gestire e distribuire il traffico alle repliche scalate all'interno della rete Docker.

    Per fermare e rimuovere tutti e tre i contenitori, il comando rimane lo stesso:

    docker compose down

Configurazione della rete personalizzata

Per impostazione predefinita, Docker Compose crea una singola rete bridge per la tua applicazione. Ogni servizio nel file vi è collegato, ed è così che il container wordpress è stato in grado di trovare il container db semplicemente usando il suo nome di servizio (db).

Tuttavia, puoi definire le tue reti personalizzate per un migliore isolamento e controllo.

Modifichiamo l'esempio di WordPress per utilizzare una rete bridge personalizzata.

services:
  db:
    image: mysql:8.0
    ...
    networks:
      - app_net

  wordpress:
    image: wordpress:latest
    ...
    ports:
      - "8001:80"
    depends_on:
      - db
    networks:
      - app_net

volumes:
  db_data:

networks:
  app_net:
    driver: bridge

Ecco cosa abbiamo aggiunto:

  • networks (livello superiore): Questo definisce una nuova rete chiamata app_net e specifica che dovrebbe usare il driver standard bridge.
  • networks (a livello di servizio): Sia sotto db che wordpress, questa chiave li collega alla nostra rete app_net.

Se avessi un terzo servizio (come uno strumento di analisi) che non colleghi a app_net, sarebbe completamente isolato e incapace di comunicare con i container db o wordpress.

Per il clustering multi-host con Docker Swarm, dovresti cambiare il driver da bridge a overlay. Il driver bridge serve per la comunicazione tra container su un singolo host, che è lo standard per la maggior parte dei casi d'uso di Docker Compose.

Utilizzo di file di configurazione modulari

Man mano che le tue applicazioni crescono, il file docker-compose.yml può diventare grande e difficile da gestire. Docker Compose supporta la direttiva include, che ti permette di dividere la configurazione su più file.

Immagina di voler separare le definizioni di WordPress e del database, e magari avere un comune docker-compose.override.yml per le impostazioni specifiche dello sviluppo (come il binding di una porta sul database).

La struttura delle tue directory potrebbe sembrare così:

compose-demo/
├── docker-compose.yml
├── docker-compose.db.yml
├── docker-compose.web.yml

Questo file definirà solo il servizio db.

services:
  db:
    image: mysql:8.0
    container_name: mysql_db
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: <^your_root_password_here<^>
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: <^your_wordpress_password_here<^>
    restart: unless-stopped

volumes:
  db_data:

Questo file definirà solo il servizio wordpress.

services:
  wordpress:
    image: wordpress:latest
    container_name: wordpress_app
    ports:
      - "8001:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: <^your_wordpress_password_here<^>
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - ./wp_content:/var/www/html/wp-content
    depends_on:
      - db
    restart: unless-stopped

Ora, il tuo file principale docker-compose.yml diventa molto semplice. Usa solo include per includere gli altri file.

include:
  - docker-compose.db.yml
  - docker-compose.web.yml

Quando esegui docker compose up -d, Compose leggerà tutti e tre i file, unirà le configurazioni e avvierà i servizi db e wordpress esattamente come se fossero definiti in un unico file. Questo approccio rende la tua configurazione molto più modulare e riutilizzabile.

Nota: La direttiva include: richiede Docker Compose v2.20 o successiva. Se il tuo sistema utilizza una versione precedente, puoi combinare i file usando docker compose -f docker-compose.db.yml -f docker-compose.web.yml up.

Migrare da docker-compose (v1) a docker compose (v2)

Il comando docker compose che hai installato nel Passo 1 è «Compose v2». È un plugin basato su Go integrato direttamente nel CLI di Docker.

La versione originale, “Compose v1,” era uno strumento Python separato richiamato con docker-compose (con trattino). A partire da luglio 2023, Compose v1 non è più supportato ed è stato deprecato.

Modifiche principali e compatibilità retroattiva

  • Il Comando: Il cambiamento più evidente riguarda il comando. Il trattino (docker-compose) è ora uno spazio (docker compose).
  • Installazione: la versione v1 è stata installata con pip. La versione v2 è inclusa con Docker Desktop o installata come plugin CLI, come hai fatto nel Passaggio 1.
  • File YAML: I tuoi file docker-compose.yml sono quasi al 100% compatibili con le versioni precedenti. Compose v2 supporta pienamente le versioni di file 3.x. Non è necessario modificare i tuoi file YAML per la migrazione, solo i tuoi comandi.
  • --project-name flag: Il flag -p funziona ancora, ma il flag completo ora è --project-name invece di --project_name.

Guida alla Migrazione dei Comandi

La maggior parte dei comandi è identica, solo senza il trattino. Ecco una tabella che confronta i comandi comuni della versione 1 con i loro equivalenti nella versione 2.

Comando docker-compose (v1)Comando docker compose (v2)Note
docker-compose up -d
docker compose up -d
Nessun cambiamento nella sintassi.
docker-compose down
docker compose down
Nessun cambiamento nella sintassi.
docker-compose ps
docker compose ps
Nessun cambiamento nella sintassi.
docker-compose logs
docker compose logs
Nessun cambiamento nella sintassi.
docker-compose stop
docker compose stop
Nessun cambiamento nella sintassi.
docker-compose build
docker compose build
Nessun cambiamento nella sintassi.
docker-compose exec web bash
docker compose exec web bash
Nessun cambiamento nella sintassi.
docker-compose run web bash
docker compose run web bash
run crea un nuovo container. exec viene eseguito in uno esistente.
docker-compose up --scale web=3
docker compose up --scale web=3
Il flag --scale è ancora supportato nella versione 2.

Come puoi vedere, per la maggior parte degli usi quotidiani, l'unica modifica è docker-compose -> docker compose. Se utilizzi script, puoi aggiornarli semplicemente rimuovendo il trattino.

Se hai ancora installato il vecchio docker-compose v1, puoi rimuoverlo per evitare confusione:

sudo pip3 uninstall docker-compose

Oppure, se è stato installato tramite apt:

sudo apt remove docker-compose

Risoluzione dei comuni problemi di Docker Compose

Quando lavori con Docker Compose, potresti incontrare problemi legati alla sintassi dei file, ai permessi o ai conflitti di runtime dei container. La maggior parte dei problemi può essere diagnosticata e risolta controllando metodicamente la tua configurazione, i permessi e i log dei container.

Esaminiamo alcuni degli errori più comuni e le loro soluzioni.

Permesso Negato (Socket Docker)

Questo è uno degli errori più comuni per i nuovi utenti di Docker. Esegui docker compose up e vedi un messaggio di errore relativo al socket del demone Docker.

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
  • Problema: Il tuo utente non root non ha il permesso di comunicare con il demone Docker, che viene eseguito come root.

  • Soluzione: Devi aggiungere il tuo utente al gruppo docker, che è stato creato durante l’installazione di Docker.

    1. Aggiungi il tuo utente al gruppo docker:

      sudo usermod -aG docker ${USER}
    2. Perché la nuova appartenenza al gruppo abbia effetto, devi uscire e accedere di nuovo.

    3. In alternativa, puoi attivare le modifiche del gruppo per la tua sessione del terminale corrente digitando:

      newgrp docker

    Questo dovrebbe risolvere eventuali errori di autorizzazione relativi al socket Docker.

Errori di sintassi e di indentazione YAML

Docker Compose non riesce ad avviarsi e segnala che il tuo file docker-compose.yml non è valido.

ERROR: The Compose file './docker-compose.yml' is invalid because:
services.web.ports contains an invalid type, it should be a list

Oppure :

mapping values are not allowed in this context at line 5
  • Problema: Il file docker-compose.yml si basa su una sintassi YAML rigorosa. L'errore più comune è l'indentazione errata. YAML utilizza spazi, non tabulazioni, per definire la struttura.
  • Soluzione: Controlla attentamente l'indentazione del tuo file docker-compose.yml.

    • Lo standard prevede due spazi per ogni livello di indentazione.
    • Assicurati che tutte le chiavi allo stesso livello (come version, services, volumes) inizino nella stessa colonna.
    • Assicurati che tutte le sotto-chiavi (come image, ports, volumes sotto un servizio) siano indentate di due spazi in più rispetto al loro servizio principale (ad esempio, web).
    • Usa un editor di codice con un linter YAML per evidenziare automaticamente gli errori di sintassi.

Conflitti di porte

Provi ad avviare il tuo ambiente, ma il comando fallisce con un messaggio di errore che indica che l'indirizzo è già in uso.

Error starting userland proxy: listen tcp 0.0.0.0:8000: bind: address already in use
  • Problema: Un altro processo sulla tua macchina host sta già ascoltando sulla porta che stai cercando di mappare (in questo caso, la porta 8000). Spesso si tratta di un altro container Docker o di un server di sviluppo locale.

  • Soluzione: Hai due opzioni:

    1. Ferma l'altro processo. Puoi trovare il processo che utilizza la porta con questo comando:

      sudo lsof -i :8000

      Se si tratta di un altro container Docker, interrompilo con docker stop <container_id>.

    2. Modifica la porta dell'host nel tuo file docker-compose.yml. Spesso questa è la soluzione più semplice. Cambia la mappatura delle ports da "8000:80" a un'altra porta, ad esempio "8001:80".

      ...
      ports:
        - "8001:80" # Changed from 8000
      ...
    3. docker-compose.yml

Il servizio fallisce con Connessione Rifiutata (depends_on)

In un'applicazione multi-servizio (come l'esempio con WordPress e MySQL), il container wordpress si avvia ma i suoi log mostrano Connessione rifiutata o Il server MySQL si è disconnesso quando tenta di connettersi al servizio db.

  • Problema: Hai usato depends_on, ma questa direttiva aspetta solo che il contenitore db si avvii. Non aspetta che l'applicazione MySQL all'interno del contenitore sia completamente inizializzata e pronta a ricevere connessioni.

  • Soluzione: L'applicazione (in questo caso, WordPress) deve essere configurata per riprovare la connessione. La maggior parte delle immagini moderne ha questa logica di tentativo integrata. Per le immagini che non lo fanno, è necessario implementare un controllo dello stato.

    Puoi aggiungere un healthcheck al tuo servizio db. Il depends_on del servizio wordpress può quindi essere configurato per attendere che il database sia "healthy" (sano), non solo "started" (avviato).

Esempio di controllo dello stato di MySQL:

services:
  db:
    image: mysql:8.0
    ...
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p<^your_root_password_here<^>"]
      interval: 10s
      timeout: 5s
      retries: 5

  wordpress:
    image: wordpress:latest
    ...
    depends_on:
      db:
        condition: service_healthy # This now waits for the healthcheck
    ...

Errori con Volumi e Mount Bind

Potresti incontrare errori di autorizzazione nei log del tuo container o scoprire che la directory dei dati del tuo container è vuota.

Permessi File/Directory

  • Problema: Il contenitore gira come un utente specifico (ad esempio, www-data con ID utente 33), ma la directory dell'host che hai montato è di proprietà del tuo utente (ad esempio, ubuntu con ID utente 1000). L'utente del contenitore non ha il permesso di scrivere nella directory dell'host.

  • Soluzione: Cambia la proprietà della directory host in modo che corrisponda all'ID utente all'interno del container. Puoi trovare l'ID utente del container eseguendo docker compose exec <service_name> id. Ad esempio, se l'ID è 33 (comune per www-data):

    sudo chown -R 33:33 ./wp_content

Problemi di percorso relativo

  • Problema: Il tuo docker-compose.yml utilizza un percorso relativo come ./app, ma il tuo file index.html non viene servito.

  • Soluzione: Docker Compose interpreta i percorsi relativi dalla directory in cui esegui il comando docker compose up. Esegui sempre i comandi di Compose dalla stessa directory che contiene il file docker-compose.yml.

Reti e scoperta dei servizi

I log del tuo container dell'applicazione mostrano Host non found o Impossibile risolvere l'host: db.

  • Problema: Il tuo container wordpress non riesce a trovare il container db sulla rete.
  • Soluzione: Per impostazione predefinita, Docker Compose crea una rete e vi collega tutti i servizi. I servizi possono trovare gli altri utilizzando i loro nomi di servizio.

    1. Verifica i nomi dei servizi: Assicurati che il nome host nella configurazione della tua applicazione (ad esempio, la variabile d'ambiente WORDPRESS_DB_HOST) sia esattamente uguale al nome del servizio nel tuo docker-compose.yml (ad esempio, db).

    2. Ispeziona la rete: Usa docker compose ps per trovare il nome del tuo progetto (ad es., compose-demo). Poi, ispeziona la rete predefinita:

      docker network inspect compose-demo_default

      L'output JSON elencherà tutti i container collegati a questa rete. Se uno dei tuoi servizi manca, controlla il tuo docker-compose.yml per eventuali configurazioni personalizzate di networks che potrebbero isolarlo.

Incongruenza del comando (v1 vs. v2)

Digiti docker-compose up (con un trattino) e vedi un errore “comando non trovato”.

docker-compose: command not found
  • Problema: Stai cercando di usare il comando per Compose v1, che è uno strumento Python obsoleto. Questa guida installa Compose v2, che è un plugin integrato direttamente nel CLI di Docker.
  • Soluzione: Usa il comando corretto sostituendo il trattino (-) con uno spazio.
docker-compose (v1)docker compose (v2)
docker-compose updocker compose up
docker-compose downdocker compose down
docker-compose psdocker compose ps
docker-compose logsdocker compose logs

Usa sempre docker compose (spazio) quando segui questa guida.

Domande frequenti

1. A cosa serve Docker Compose?

Docker Compose è uno strumento per definire ed eseguire applicazioni Docker multi-container.

Utilizza un singolo file YAML (di default, docker-compose.yml) per configurare tutti i componenti della tua applicazione, chiamati servizi. Questo file definisce anche le reti che permettono ai servizi di comunicare tra loro e i volumi utilizzati per i dati persistenti.

Con questo unico file, puoi gestire l'intero stack della tua applicazione con comandi semplici:

  • docker compose up avvia ed esegue l'intera applicazione, inclusi tutti i container, le reti e i volumi specificati.
  • docker compose down ferma e rimuove tutti i container, le reti e i volumi creati dalla tua applicazione.

È particolarmente utile per gestire applicazioni che richiedono più componenti, come un sito web che necessita di un server web (come Nginx), un backend per applicazioni (come WordPress) e un database (come MySQL).

2. Come installo Docker Compose su Ubuntu?

Il metodo consigliato è installare Docker Compose come plugin per la CLI di Docker. Questo si fa installando il pacchetto docker-compose-plugin dal repository ufficiale apt di Docker.

  1. Per prima cosa, assicurati di aver seguito la documentazione ufficiale di Docker per configurare il repository apt di Docker sul tuo sistema Ubuntu.

  2. Aggiorna la lista dei pacchetti:

    sudo apt update
  3. Installa il plugin Docker Compose:

    sudo apt install docker-compose-plugin
  4. Verifica l'installazione controllando la versione. Il comando utilizza uno spazio, non un trattino.

    docker compose version

3. Come posso aggiornare Docker Compose all'ultima versione?

Poiché Docker Compose (v2) è installato come pacchetto di sistema usando apt, puoi aggiornarlo utilizzando il normale processo di aggiornamento del software di Ubuntu.

  1. Aggiorna l'indice dei pacchetti locali:

    sudo apt update
  2. Esegui un aggiornamento dell'intero sistema, che includerà il plugin Compose:

    sudo apt upgrade

    In alternativa, se vuoi aggiornare solo il plugin, puoi eseguire:

    sudo apt install --only-upgrade docker-compose-plugin

4. Docker Compose può essere utilizzato negli ambienti di produzione?

Sì, Docker Compose è spesso utilizzato in produzione, in particolare per applicazioni che girano su un singolo host.

Fornisce un modo semplice per definire, distribuire e gestire il ciclo di vita dei servizi, delle reti e dei volumi della tua applicazione. Per un'installazione su un singolo server, è una soluzione molto efficace e facile da gestire.

Per scenari più complessi che richiedono il coordinamento di container su più host (un cluster), sono più comuni altri strumenti. Questi includono Docker Swarm (che utilizza una sintassi di file Compose simile) e Kubernetes (che è lo standard del settore per l'orchestrazione di container su larga scala).

5. Qual è la differenza tra Docker e Docker Compose?

Questa tabella illustra le principali differenze tra il Docker CLI e il Docker Compose CLI.

Caratteristicadocker (Motore Docker)docker compose (Plugin Compose)
AmbitoGestisce gli oggetti Docker individuali.Gestisce un applicazione completa con più contenitori come un'unica unità.
Uso principaleCreazione di immagini (docker build), esecuzione di singoli container (docker run), gestione di container (docker ps), immagini, volumi e reti.Orchestrare più servizi definiti in un file docker-compose.yml.
ComandiComandi di basso livello concentrati su un singolo oggetto. Esempio: docker run -d -p 80:80 -v ./:/app nginxComandi di alto livello per l'intera applicazione. Esempio: docker compose up
AnalogiaUn mattoncino (un singolo contenitore).Il progetto e il responsabile della costruzione dell'intero edificio (l'applicazione).

In breve, usi docker per interagire con un singolo container. Usi docker compose per gestire l'intero stack della tua applicazione (ad es., web, app, db) tutto in una volta.

6. Come eseguo più container con Docker Compose?

Esegui più container definendoli come servizi nel tuo file docker-compose.yml.

  1. Crea un file chiamato docker-compose.yml.

  2. All'interno di questo file, utilizza la chiave services: per definire ogni container che vuoi eseguire.

    Ecco un esempio pratico che definisce e avvia due container: un sito WordPress e un database MySQL.

    services:
      db:
        # This is the first service (container)
        image: mysql:8.0
        environment:
          MYSQL_ROOT_PASSWORD: <^your_password_here<^>
          MYSQL_DATABASE: wordpress
        volumes:
          - db_data:/var/lib/mysql
    
      wordpress:
        # This is the second service (container)
        image: wordpress:latest
        ports:
          - "8001:80"
        environment:
          WORDPRESS_DB_HOST: db
          WORDPRESS_DB_PASSWORD: <^your_password_here<^>
        depends_on:
          - db
    
    volumes:
      db_data:
  3. docker-compose.yml

  4. Salva il file e apri un terminale nella stessa directory.

  5. Esegui un unico comando per avviare entrambi i container:

    docker compose up -d

Docker Compose leggerà il file, creerà una rete condivisa per i servizi, scaricherà le immagini mysql e wordpress e avvierà un container per ciascun servizio.

7. Perché usare Docker Compose per lo sviluppo?

Docker Compose è uno strumento standard per gli ambienti di sviluppo perché risolve diversi problemi comuni.

  • Ambienti Coerenti: Garantisce che ogni sviluppatore del team esegua gli stessi servizi (database, cache, server web) con le stesse versioni e configurazioni. Questo è definito nel file docker-compose.yml, che viene incluso nel controllo delle versioni. Ciò elimina il problema del «funziona sulla mia macchina».

  • Semplicità: Sostituisce script di configurazione complessi e lunghe istruzioni docker run. Uno sviluppatore deve solo eseguire docker compose up per avviare l'intero stack dell'applicazione e docker compose down per fermarlo.

  • Isolamento dei Servizi: Gli sviluppatori possono lavorare su più progetti sulla stessa macchina senza conflitti di dipendenze. Il Progetto A può utilizzare PostgreSQL 9.6 e il Progetto B può utilizzare PostgreSQL 14, poiché ogni database viene eseguito in un container isolato gestito dal proprio file Compose.

  • Test di integrazione facili: Poiché Compose avvia tutte le dipendenze di un'applicazione insieme, crea un ambiente locale perfetto per eseguire test di integrazione che verificano come i servizi interagiscono tra loro.

Conclusione

In questa guida, hai installato Docker Compose e configurato un'applicazione multi-contenitore completa. Hai iniziato con un file docker-compose.yml di base per un web server Nginx e sei passato a uno stack più complesso e realistico che coinvolge un'applicazione WordPress e un database MySQL. Hai imparato a gestire l'intero ciclo di vita dell'applicazione, dalla creazione e esecuzione dei servizi fino alla loro interruzione e rimozione.

Ora conosci i concetti chiave per gestire efficacemente le applicazioni, inclusi il ridimensionamento dei servizi, le definizioni di rete personalizzate e la suddivisione della tua configurazione in file modulari utilizzando la direttiva include. Seguendo la guida alla migrazione e i passaggi per la risoluzione dei problemi, puoi anche risolvere problemi comuni come conflitti di porte, errori “Permesso negato” e errori di sintassi YAML. Le competenze trattate qui ti permetteranno di costruire ambienti di sviluppo coerenti e riproducibili e di distribuire applicazioni su un singolo host con sicurezza.

Per un riferimento completo di tutti i comandi docker compose disponibili, consulta la documentazione ufficiale.

Per ulteriori tutorial su Docker, consulta i seguenti articoli:

  • Come Installare Docker su Ubuntu – Guida Passo Passo
  • Come installare WordPress con Docker Compose

Grazie per aver imparato con la community di Linux-Console.net.