Docker Compose: come orchestrare app di container

Docker Compose contribuisce a semplificare la scalabilità e la distribuzione delle applicazioni in Docker automatizzando la gestione dei contenitori. In questo tutorial, esamineremo approfonditamente la configurazione e l’uso di Docker Compose, per permetterti di sfruttarlo al meglio nel tuo ambiente di produzione.

Che cos’è Docker Compose?

Docker Compose serve a gestire le applicazioni e ad aumentare l’efficienza nello sviluppo dei container. Gli elementi di configurazione vengono impostati in un singolo file YAML, rendendo le applicazioni facili da creare e da scalare. Docker Compose si utilizza soprattutto per configurare un ambiente locale. Può però anche far parte di un flusso di lavoro di Continuous Integration / Continuous Delivery (CI/CD). Chi lavora con Docker Compose può definire una versione specifica dei container per i test o per una fase specifica della pipeline. In questo modo è più facile identificare i problemi e risolvere i bug prima che entrino in produzione.

Docker Compose: requisiti di sistema

Per l’orchestrazione di container sono necessari sia Docker Engine che Docker Compose. Pertanto, occorre che il sistema disponga di uno dei seguenti elementi:

  • Docker Engine e Docker Compose: possono essere installati come programmi binari autonomi.
  • Docker Desktop: ambiente di sviluppo con interfaccia grafica che include già Docker Engine e Docker Compose.
Consiglio

Scopri come installare Docker Compose su diversi sistemi operativi nei nostri tutorial:

Come utilizzare Docker Compose: procedura guidata

Di seguito, dimostriamo i concetti di Docker Compose con una semplice applicazione web Python nella quale le visite vengono conteggiate con un contatore. Per farlo, ricorriamo al framework Python Flask e al database in-memory Redis. Non occorre installare Python o Redis, dato che vengono forniti come immagini Docker.

Primo passaggio: creare un file di progetto

Apri il terminale e crea una nuova cartella per il progetto.

$ mkdir composedemo
shell

Passa quindi alla directory.

$ cd composedemo
shell

In questa cartella crea il file app.py e inserisci il seguente codice:

import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)
@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I was here {} times.\n'.format(count)
python

Come nome host utilizziamo “Redis” e la porta predefinita “6379”. Specifichiamo inoltre che la funzione get_hit_count() deve fare diversi tentativi di connessione al servizio. È una scelta consigliata, perché Redis potrebbe non essere ancora disponibile all’avvio dell’applicazione o potrebbero verificarsi problemi di connessione nel corso dell’esecuzione.

Definisci ora il file requirements.txt con le dipendenze:

flask
redis
plaintext

Secondo passaggio: configurare il Dockerfile

Il Dockerfile è usato per l’immagine Docker. Tutte le dipendenze di cui l’applicazione Python ha bisogno sono specificate qui.


FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
shell

Docker viene così istruito a utilizzare l’immagine di Python 3.7. Impostiamo anche le variabili d’ambiente per il comando flask. Con apk add installiamo gcc e altre dipendenze. EXPOSE specifica che il contenitore deve monitorare la porta 5000. Mediante COPY il contenuto della cartella corrente viene copiato nella cartella di lavoro /code. Come comando predefinito per il contenitore impostiamo flask run.

Verifica che il file Docker sia stato salvato senza estensione, perché alcuni editor aggiungono automaticamente il suffisso .txt.

Terzo passaggio: generare il file YAML

Configuriamo i servizi “redis” e “web” in docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
    redis:
        image: "redis:alpine"
yaml

Il servizio web utilizza l’immagine creata dal Dockerfile. Associa il contenitore e il computer host alla porta 8000, mentre il server web Flask opera sulla porta 5000. L’immagine di Redis, invece, proviene semplicemente dall’hub ufficiale di Docker.

Quarto passaggio: eseguire l’applicazione per mezzo di Compose

Avvia l’applicazione a partire dalla cartella del progetto.

docker compose up
shell

Digita http://localhost:8000 nel browser. Puoi immettere anche http://127.0.0.1:8000.

Dovrebbe apparire il seguente messaggio:

Applicazione Docker Compose: output su browser del contatore delle visite
Il browser ti mostrerà il numero delle visite.

Ricarica la pagina. Ora le visite dovrebbero essere aumentate a 2.

Nuova apertura dell’applicazione Docker Compose
Il numero delle visite è aumentato di 1.

Interrompi l’applicazione in questo modo:

$ docker compose down
shell

In alternativa, usa la combinazione Ctrl + C nel terminale in cui hai avviato l’applicazione.

Quinto passaggio: aggiungere un bind mount

È possibile aggiungere un bind mount al servizio web servendosi di docker-compose.yml.

version: "3.9"
services:
    web:
        build: .
        ports:
            - "8000:5000"
        volumes:
            - .:/code
        environment:
            FLASK_DEBUG: "true"
    redis:
        image: "redis:alpine"
yaml

In volumes specifichiamo che la cartella del progetto corrente deve essere collegata alla cartella /code all’interno del contenitore. Ciò consente di modificare il codice senza dover ricreare l’immagine. La variabile di ambiente FLASK_DEBUG indica a flask run di operare in modalità di sviluppo.

Sesto passaggio: creare ed eseguire una nuova applicazione

Immetti il seguente comando nel terminale per ricostruire il file Compose:

docker compose up
shell

Settimo passaggio: aggiornare l’applicazione

Dal momento che stai utilizzando un bind mount per la tua applicazione, puoi modificare il tuo codice e vedere automaticamente le modifiche senza dover ricreare l’immagine.

Scrivi un nuovo test di benvenuto in app.py.

return ‘Hello from Docker! I was here {} times.\n’.format(count)
python

Aggiorna il browser per verificare che le modifiche siano state adottate.

Applicazione Docker Compose: testo di benvenuto modificato
Il testo di benvenuto dell’applicazione Python è stato opportunamente modificato.

Ottavo passaggio: ulteriori comandi

L’opzione --help mostra un elenco di comandi disponibili per Docker Compose:

docker compose --help
shell

Per eseguire Docker Compose in background, è possibile aggiungere l’argomento -d:

docker compose up -d
shell

Con down vengono rimossi tutti i contenitori. L’opzione --volumes cancella anche i volumi utilizzati dal contenitore Redis.

docker compose down --volumes
shell
Consiglio

Per imparare a usare Docker puoi avvalerti di alcuni nostri articoli della Digital Guide, quali il tutorial su Docker e la panoramica sui comandi Docker.

Per offrirti una migliore esperienza di navigazione online questo sito web usa dei cookie, propri e di terze parti. Continuando a navigare sul sito acconsenti all’utilizzo dei cookie. Scopri di più sull’uso dei cookie e sulla possibilità di modificarne le impostazioni o negare il consenso.