Docker Compose con­tri­bui­sce a sem­pli­fi­ca­re la sca­la­bi­li­tà e la di­stri­bu­zio­ne delle ap­pli­ca­zio­ni in Docker au­to­ma­tiz­zan­do la gestione dei con­te­ni­to­ri. In questo tutorial, esa­mi­ne­re­mo ap­pro­fon­di­ta­men­te la con­fi­gu­ra­zio­ne e l’uso di Docker Compose, per per­met­ter­ti di sfrut­tar­lo al meglio nel tuo ambiente di pro­du­zio­ne.

Che cos’è Docker Compose?

Docker Compose serve a gestire le ap­pli­ca­zio­ni e ad aumentare l’ef­fi­cien­za nello sviluppo dei container. Gli elementi di con­fi­gu­ra­zio­ne vengono impostati in un singolo file YAML, rendendo le ap­pli­ca­zio­ni facili da creare e da scalare. Docker Compose si utilizza so­prat­tut­to per con­fi­gu­ra­re un ambiente locale. Può però anche far parte di un flusso di lavoro di Con­ti­nuous In­te­gra­tion / Con­ti­nuous 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 iden­ti­fi­ca­re i problemi e risolvere i bug prima che entrino in pro­du­zio­ne.

Docker Compose: requisiti di sistema

Per l’or­che­stra­zio­ne 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 in­stal­la­ti come programmi binari autonomi.
  • Docker Desktop: ambiente di sviluppo con in­ter­fac­cia grafica che include già Docker Engine e Docker Compose.
Consiglio

Scopri come in­stal­la­re Docker Compose su diversi sistemi operativi nei nostri tutorial:

Come uti­liz­za­re Docker Compose: procedura guidata

Di seguito, di­mo­stria­mo i concetti di Docker Compose con una semplice ap­pli­ca­zio­ne web Python nella quale le visite vengono con­teg­gia­te con un contatore. Per farlo, ri­cor­ria­mo al framework Python Flask e al database in-memory Redis. Non occorre in­stal­la­re 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 uti­liz­zia­mo “Redis” e la porta pre­de­fi­ni­ta “6379”. Spe­ci­fi­chia­mo inoltre che la funzione get_hit_count() deve fare diversi tentativi di con­nes­sio­ne al servizio. È una scelta con­si­glia­ta, perché Redis potrebbe non essere ancora di­spo­ni­bi­le all’avvio dell’ap­pli­ca­zio­ne o po­treb­be­ro ve­ri­fi­car­si problemi di con­nes­sio­ne nel corso dell’ese­cu­zio­ne.

Definisci ora il file re­qui­re­men­ts.txt con le di­pen­den­ze:

flask
redis
plaintext

Secondo passaggio: con­fi­gu­ra­re il Doc­ker­fi­le

Il Doc­ker­fi­le è usato per l’immagine Docker. Tutte le di­pen­den­ze di cui l’ap­pli­ca­zio­ne Python ha bisogno sono spe­ci­fi­ca­te qui.

# syntax=docker/dockerfile:1
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 uti­liz­za­re l’immagine di Python 3.7. Im­po­stia­mo anche le variabili d’ambiente per il comando flask. Con apk add in­stal­lia­mo gcc e altre di­pen­den­ze. EXPOSE specifica che il con­te­ni­to­re deve mo­ni­to­ra­re la porta 5000. Mediante COPY il contenuto della cartella corrente viene copiato nella cartella di lavoro /code. Come comando pre­de­fi­ni­to per il con­te­ni­to­re im­po­stia­mo flask run.

Verifica che il file Docker sia stato salvato senza esten­sio­ne, perché alcuni editor ag­giun­go­no au­to­ma­ti­ca­men­te il suffisso .txt.

Terzo passaggio: generare il file YAML

Con­fi­gu­ria­mo 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 Doc­ker­fi­le. Associa il con­te­ni­to­re e il computer host alla porta 8000, mentre il server web Flask opera sulla porta 5000. L’immagine di Redis, invece, proviene sem­pli­ce­men­te dall’hub ufficiale di Docker.

Quarto passaggio: eseguire l’ap­pli­ca­zio­ne per mezzo di Compose

Avvia l’ap­pli­ca­zio­ne 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:

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

Ricarica la pagina. Ora le visite do­vreb­be­ro essere aumentate a 2.

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

In­ter­rom­pi l’ap­pli­ca­zio­ne in questo modo:

$ docker compose down
shell

In al­ter­na­ti­va, usa la com­bi­na­zio­ne Ctrl + C nel terminale in cui hai avviato l’ap­pli­ca­zio­ne.

Quinto passaggio: ag­giun­ge­re un bind mount

È possibile ag­giun­ge­re un bind mount al servizio web ser­ven­do­si 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 spe­ci­fi­chia­mo che la cartella del progetto corrente deve essere collegata alla cartella /code all’interno del con­te­ni­to­re. Ciò consente di mo­di­fi­ca­re 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 ap­pli­ca­zio­ne

Immetti il seguente comando nel terminale per ri­co­strui­re il file Compose:

docker compose up
shell

Settimo passaggio: ag­gior­na­re l’ap­pli­ca­zio­ne

Dal momento che stai uti­liz­zan­do un bind mount per la tua ap­pli­ca­zio­ne, puoi mo­di­fi­ca­re il tuo codice e vedere au­to­ma­ti­ca­men­te 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 ve­ri­fi­ca­re che le modifiche siano state adottate.

Immagine: Applicazione Docker Compose: testo di benvenuto modificato
Il testo di benvenuto dell’ap­pli­ca­zio­ne Python è stato op­por­tu­na­men­te mo­di­fi­ca­to.

Ottavo passaggio: ulteriori comandi

L’opzione --help mostra un elenco di comandi di­spo­ni­bi­li per Docker Compose:

docker compose --help
shell

Per eseguire Docker Compose in back­ground, è possibile ag­giun­ge­re l’argomento -d:

docker compose up -d
shell

Con down vengono rimossi tutti i con­te­ni­to­ri. L’opzione --volumes cancella anche i volumi uti­liz­za­ti dal con­te­ni­to­re 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 pa­no­ra­mi­ca sui comandi Docker.

Vai al menu prin­ci­pa­le