Esercitazione: Creare app multi-contenitore con MySQL e Docker Compose

In questa esercitazione si apprenderà come creare app multi-contenitore. Questa esercitazione si basa sulle esercitazioni introduttive, Introduzione a Docker e Visual Studio Code. In questa esercitazione avanzata si aggiornerà l'applicazione in modo che funzioni come descritto in questo diagramma e si apprenderà come:

  • Avviare MySQL.
  • Eseguire l'app con MySQL.
  • Creare il file compose.
  • Eseguire lo stack di applicazioni.

Diagram shows two containers labeled Todo App and MySQL connected with a line.

L'uso di più contenitori consente di dedicare contenitori per attività specializzate. Ogni contenitore deve eseguire una sola operazione e farlo bene.

Ecco alcuni motivi per cui è possibile usare app multi-contenitore:

  • Separare i contenitori per gestire LE API e i front-end in modo diverso rispetto ai database.
  • I contenitori consentono di aggiornare le versioni in isolamento.
  • Anche se è possibile usare un contenitore per il database in locale, è consigliabile usare un servizio gestito per il database in produzione.
  • L'esecuzione di più processi richiede un processo di gestione, che aggiunge complessità all'avvio/arresto del contenitore.

Prerequisiti

Questa esercitazione continua la serie di esercitazioni, a partire da Creare un'app contenitore. Iniziare con quello, che include i prerequisiti. Eseguire quindi l'esercitazione Rendere persistenti i dati nell'app.

Sono necessari anche gli elementi seguenti:

  • Docker Compose.

    Docker Desktop per Windows o Mac include Docker Compose. Eseguire questo comando per verificare:

    docker-compose version
    

    Se si usa il sistema operativo Linux, installare Docker Compose.

Come per le esercitazioni precedenti, è possibile eseguire la maggior parte delle attività dalla visualizzazione VS Code EXPLORER o dalla visualizzazione DOCKER. È possibile selezionare Terminale>nuovo terminale per aprire una finestra della riga di comando in VS Code. È anche possibile eseguire comandi in una finestra Bash. A meno che non sia specificato, qualsiasi comando etichettato come Bash può essere eseguito in una finestra Bash o nel terminale di VS Code.

Avviare MySQL

Per impostazione predefinita, i contenitori vengono eseguiti in isolamento. Non conoscono nulla su altri processi o contenitori nello stesso computer. Per consentire a un contenitore di comunicare con un altro, usare la rete.

Se due contenitori si trovano nella stessa rete, possono comunicare tra loro. Se non lo sono, non possono.

Esistono due modi per inserire un contenitore in una rete: assegnarlo all'avvio o connettere un contenitore esistente. In questo esempio si crea prima la rete e si collega il contenitore MySQL all'avvio.

  1. Creare la rete usando questo comando.

    docker network create todo-app
    
  2. Avviare un contenitore MySQL e collegarlo alla rete.

    docker run -d 
        --network todo-app --network-alias mysql 
        -v todo-mysql-data:/var/lib/mysql 
        -e MYSQL_ROOT_PASSWORD=<your-password> 
        -e MYSQL_DATABASE=todos 
        mysql:5.7
    

    Questo comando definisce anche le variabili di ambiente. Per altre informazioni, vedere Presentazione dell'hub Docker di MySQL.

    Il comando specifica un alias di rete, mysql.

  3. Ottenere l'ID contenitore usando il docker ps comando .

  4. Per verificare che il database sia operativo, connettersi al database.

    docker exec -it <mysql-container-id> mysql -p
    

    Immettere la password usata, in precedenza, quando richiesto.

  5. Nella shell MySQL elencare i database e verificare che venga visualizzato il todos database.

    SHOW DATABASES;
    

    Viene visualizzato l'output seguente.

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | todos              |
    +--------------------+
    5 rows in set (0.00 sec)
    
  6. Immettere exit quando si è pronti per tornare al prompt dei comandi del terminale.

Eseguire l'app con MySQL

L'app todo supporta l'impostazione delle variabili di ambiente per specificare le impostazioni di connessione mySQL.

  • MYSQL_HOST Nome host per il server MySQL.
  • MYSQL_USER Nome utente da usare per la connessione.
  • MYSQL_PASSWORD Password da utilizzare per la connessione.
  • MYSQL_DB Database da utilizzare dopo la connessione.

Avviso

L'uso delle variabili di ambiente per impostare le impostazioni di connessione è accettabile per lo sviluppo. È consigliabile evitare questa procedura per l'esecuzione di applicazioni nell'ambiente di produzione. Per altre informazioni, vedere Perché non usare le variabili di ambiente per i dati segreti.

Un meccanismo più sicuro consiste nell'usare il supporto segreto fornito dal framework di orchestrazione dei contenitori. Nella maggior parte dei casi, questi segreti vengono montati come file nel contenitore in esecuzione.

Questa procedura avvia l'app e connette il contenitore al contenitore MySQL.

  1. Usare il comando docker run seguente. Specifica le variabili di ambiente precedenti.

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:20-alpine 
      sh -c "yarn install && yarn run dev"
    
  2. In VS Code, nella visualizzazione Docker fare clic con il pulsante destro del mouse sul contenitore dell'app e scegliere Visualizza log. Per visualizzare i log dalla riga di comando, usare il docker logs comando .

    Il risultato include una riga che indica che l'app è connessa al database MySQL.

    # Previous log messages omitted
    $ nodemon src/index.js
    [nodemon] 1.19.2
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching dir(s): *.*
    [nodemon] starting `node src/index.js`
    Connected to mysql db at host mysql
    Listening on port 3000
    
  3. Immettere http://localhost:3000 nel browser. Aggiungere alcuni elementi all'elenco todo.

  4. Connessione al database MySQL, come è stato fatto nella sezione precedente. Eseguire questo comando per verificare che gli elementi vengano scritti nel database.

    docker exec -ti <mysql-container-id> mysql -p todos
    

    E nella shell MySQL eseguire i comandi seguenti.

    use todos;
    select * from todo_items;
    

    Il risultato sarà simile all'output seguente.

    +--------------------------------------+--------------------+-----------+
    | id                                   | name               | completed |
    +--------------------------------------+--------------------+-----------+
    | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! |         0 |
    | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome!        |         0 |
    +--------------------------------------+--------------------+-----------+
    

A questo punto, si dispone di un'applicazione che archivia i dati in un database esterno. Il database viene eseguito in un contenitore separato. Si sono apprese informazioni sulla rete dei contenitori.

Creare un file Docker Compose

Docker Compose consente di definire e condividere applicazioni multi-contenitore. Con Docker Compose è possibile creare un file per definire i servizi. Con un singolo comando, è possibile ruotare tutto o eliminarlo tutto.

È possibile definire lo stack di applicazioni in un file e mantenere tale file nella radice del repository del progetto, sotto il controllo della versione. Questo approccio consente ad altri utenti di contribuire al progetto. Dovranno solo clonare il repository.

  1. Nella radice del progetto dell'app creare un file denominato docker-compose.yml.

  2. Nel file compose iniziare definendo la versione dello schema.

    version: "3.7"
    

    Nella maggior parte dei casi, è consigliabile usare la versione supportata più recente. Per le versioni correnti dello schema e la matrice di compatibilità, vedere File Compose.

  3. Definire i servizi o i contenitori da eseguire come parte dell'applicazione.

    version: "3.7"
    
    services:
    

    Suggerimento

    Il rientro è significativo nei file con estensione yml . Se si sta modificando in VS Code, IntelliSense indica errori.

  4. Ecco il comando usato per il contenitore dell'app. Queste informazioni verranno aggiunte al file con estensione yml .

    docker run -dp 3000:3000 
      -w /app -v ${PWD}:/app 
      --network todo-app 
      -e MYSQL_HOST=mysql 
      -e MYSQL_USER=root 
      -e MYSQL_PASSWORD=<your-password> 
      -e MYSQL_DB=todos 
      node:20-alpine 
      sh -c "yarn install && yarn run dev"
    

    Definire la voce del servizio e l'immagine per il contenitore.

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
    

    È possibile selezionare qualsiasi nome per il servizio. Il nome diventa automaticamente un alias di rete, utile quando si definisce il servizio MySQL.

  5. Aggiungere il comando .

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
    
  6. Specificare le porte per il servizio, che corrispondono al -p 3000:3000 comando precedente.

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
    
  7. Specificare la directory di lavoro e il mapping del volume

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
    

    Nelle definizioni di volume Docker Compose è possibile usare percorsi relativi dalla directory corrente.

  8. Specificare le definizioni delle variabili di ambiente.

    version: "3.7"
    
    services:
      app:
        image: node:20-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: <your-password>
          MYSQL_DB: todos
    
  9. Aggiungere le definizioni per il servizio MySQL. Ecco il comando usato in precedenza:

    docker run -d 
      --network todo-app --network-alias mysql 
      -v todo-mysql-data:/var/lib/mysql 
      -e MYSQL_ROOT_PASSWORD=<your-password> 
      -e MYSQL_DATABASE=todos 
      mysql:5.7
    

    Definire il nuovo servizio e denominarlo mysql. Aggiungere il testo dopo la app definizione, allo stesso livello di rientro.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
    

    Il servizio ottiene automaticamente l'alias di rete. Specificare l'immagine da usare.

  10. Definire il mapping del volume.

    Specificare il volume con una volumes: sezione allo stesso livello di services:. Specificare il mapping del volume sotto l'immagine.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
    
  11. Specificare le variabili di ambiente.

    version: "3.7"
    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:5.7
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment: 
          MYSQL_ROOT_PASSWORD: <your-password>
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:
    

A questo punto, il completamento docker-compose.yml è simile al seguente:

version: "3.7"

services:
  app:
    image: node:20-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: <your-password>
      MYSQL_DB: todos

  mysql:
    image: mysql:5.7
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: <your-password>
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

Eseguire lo stack di applicazioni

Ora che hai il docker-compose.yml file, provalo.

  1. Assicurarsi che non siano in esecuzione altre copie dell'app e del database. Nell'estensione Docker fare clic con il pulsante destro del mouse su qualsiasi contenitore in esecuzione e scegliere Rimuovi. In alternativa, nella riga di comando usare il comando docker rm come negli esempi precedenti.

  2. In Esplora VS Code fare clic con il pulsante destro del mouse su docker-compose.yml e scegliere Compose Up. In alternativa, nella riga di comando usare questo comando docker.

    docker-compose up -d
    

    Il -d parametro rende il comando eseguito in background.

    Verrà visualizzato un output simile ai risultati seguenti.

    [+] Building 0.0s (0/0)
    [+] Running 2/2
    ✔ Container app-app-1    Started                                                                                                       0.9s 
    ✔ Container app-mysql-1  Running
    

    Il volume è stato creato e una rete. Per impostazione predefinita, Docker Compose crea una rete specifica per lo stack di applicazioni.

  3. Nell'estensione Docker fare clic con il pulsante destro del mouse sul contenitore dell'app e scegliere Visualizza log. Per visualizzare i log dalla riga di comando, usare il docker logs comando .

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '5.7.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000
    

    I log di ognuno dei servizi vengono interleavati in un singolo flusso. Con questo comportamento, è possibile controllare i problemi correlati alla tempistica.

    Il nome del servizio viene visualizzato all'inizio della riga per distinguere i messaggi. Per visualizzare i log per un servizio specifico, aggiungere il nome del servizio alla fine del comando logs.

  4. A questo punto, dovresti essere in grado di aprire l'app. Immettere http://localhost:3000 nel browser.

Al termine di questi contenitori, è possibile rimuoverli tutti semplicemente.

  • In Esplora risorse di VS Code fare clic con il pulsante destro del mouse su docker-compose.yml e scegliere Componi in basso.
  • Nella riga di comando, eseguire docker-compose down.

I contenitori si arrestano. La rete viene rimossa.

Per impostazione predefinita, i volumi denominati nel file compose non vengono rimossi. Se si desidera rimuovere i volumi, eseguire docker-compose down --volumes.

Pulire le risorse

I prerequisiti usati in questa serie di esercitazioni possono essere usati per lo sviluppo futuro di Docker. Non c'è motivo di eliminare o disinstallare nulla.

Passaggi successivi

In questa esercitazione sono state illustrate le app multi-contenitore e Docker Compose. Docker Compose semplifica notevolmente la definizione e la condivisione di applicazioni multiservizio.

Ecco alcune risorse che potrebbero essere utili per l'utente: