⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

Applications multi-conteneurs

Jusqu'à présent, vous avez travaillé avec des applications à conteneur unique. Mais, maintenant vous allez ajouter MySQL à la pile d'applications. La question suivante se pose souvent - "Où MySQL va-t-il s'exécuter ? L'installer dans le même conteneur ou l'exécuter séparément ?" En général, chaque conteneur devrait faire une chose et bien la faire. Voici quelques raisons d'exécuter le conteneur séparément :

  • Il y a de bonnes chances que vous deviez adapter l'échelle des API et des interfaces différemment des bases de données.
  • Les conteneurs séparés vous permettent de versionner et mettre à jour les versions de manière isolée.
  • Bien que vous puissiez utiliser un conteneur pour la base de données localement, vous pourriez vouloir utiliser un service géré pour la base de données en production. Vous ne voulez pas livrer votre moteur de base de données avec votre application alors.
  • Exécuter plusieurs processus nécessitera un gestionnaire de processus (le conteneur ne démarre qu'un seul processus), ce qui ajoute de la complexité au démarrage/arrêt du conteneur.

Et il y a plus de raisons. Donc, comme le diagramme suivant, il est préférable d'exécuter votre application dans plusieurs conteneurs.

Application Todo connectée au conteneur MySQL

Réseau de conteneurs

Rappelez-vous que les conteneurs, par défaut, s'exécutent de manière isolée et ne savent rien des autres processus ou conteneurs sur la même machine. Alors, comment permettez-vous à un conteneur de parler à un autre ? La réponse est le réseau. Si vous placez les deux conteneurs sur le même réseau, ils peuvent se parler.

Démarrer MySQL

Il y a deux façons de mettre un conteneur sur un réseau :

  • Assigner le réseau lors du démarrage du conteneur.
  • Connecter un conteneur déjà en cours d'exécution à un réseau.

Dans les étapes suivantes, vous créerez d'abord le réseau puis attacherez le conteneur MySQL au démarrage.

  1. Créez le réseau.

    $ docker network create todo-app
    
  2. Démarrez un conteneur MySQL et attachez-le au réseau. Vous allez aussi définir quelques variables d'environnement que la base de données utilisera pour initialiser la base de données. Pour en savoir plus sur les variables d'environnement MySQL, voir la section "Variables d'environnement" dans la liste Docker Hub MySQL.

    $ docker run -d \
        --network todo-app --network-alias mysql \
        -v todo-mysql-data:/var/lib/mysql \
        -e MYSQL_ROOT_PASSWORD=secret \
        -e MYSQL_DATABASE=todos \
        mysql:8.0
    
    $ docker run -d `
        --network todo-app --network-alias mysql `
        -v todo-mysql-data:/var/lib/mysql `
        -e MYSQL_ROOT_PASSWORD=secret `
        -e MYSQL_DATABASE=todos `
        mysql:8.0
    $ docker run -d ^
        --network todo-app --network-alias mysql ^
        -v todo-mysql-data:/var/lib/mysql ^
        -e MYSQL_ROOT_PASSWORD=secret ^
        -e MYSQL_DATABASE=todos ^
        mysql:8.0
    

    Dans la commande précédente, vous pouvez voir le flag --network-alias. Dans une section ultérieure, vous en apprendrez plus sur ce flag.

    Tip

    Vous remarquerez un volume nommé todo-mysql-data dans la commande ci-dessus qui est monté à /var/lib/mysql, qui est l'endroit où MySQL stocke ses données. Cependant, vous n'avez jamais exécuté une commande docker volume create. Docker reconnaît que vous voulez utiliser un volume nommé et en crée un automatiquement pour vous.

  3. Pour confirmer que vous avez la base de données en cours d'exécution, connectez-vous à la base de données et vérifiez qu'elle se connecte.

    $ docker exec -it <mysql-container-id> mysql -u root -p
    

    Quand l'invite de mot de passe apparaît, tapez secret. Dans le shell MySQL, listez les bases de données et vérifiez que vous voyez la base de données todos.

    mysql> SHOW DATABASES;
    

    Vous devriez voir une sortie qui ressemble à ceci :

    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | sys                |
    | todos              |
    +--------------------+
    5 rows in set (0.00 sec)
  4. Quittez le shell MySQL pour retourner au shell sur votre machine.

    mysql> exit
    

    Vous avez maintenant une base de données todos et elle est prête à être utilisée.

Se connecter à MySQL

Maintenant que vous savez que MySQL est en cours d'exécution, vous pouvez l'utiliser. Mais, comment l'utilisez-vous ? Si vous exécutez un autre conteneur sur le même réseau, comment trouvez-vous le conteneur ? Rappelez-vous que chaque conteneur a sa propre adresse IP.

Pour répondre aux questions ci-dessus et mieux comprendre le réseau de conteneurs, vous allez utiliser le conteneur nicolaka/netshoot, qui est livré avec beaucoup d'outils utiles pour dépanner ou déboguer les problèmes de réseau.

  1. Démarrez un nouveau conteneur en utilisant l'image nicolaka/netshoot. Assurez-vous de le connecter au même réseau.

    $ docker run -it --network todo-app nicolaka/netshoot
    
  2. À l'intérieur du conteneur, vous allez utiliser la commande dig, qui est un outil DNS utile. Vous allez rechercher l'adresse IP pour le nom d'hôte mysql.

    $ dig mysql
    

    Vous devriez obtenir une sortie comme la suivante.

    ; <<>> DiG 9.18.8 <<>> mysql
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
    
    ;; QUESTION SECTION:
    ;mysql.				IN	A
    
    ;; ANSWER SECTION:
    mysql.			600	IN	A	172.23.0.2
    
    ;; Query time: 0 msec
    ;; SERVER: 127.0.0.11#53(127.0.0.11)
    ;; WHEN: Tue Oct 01 23:47:24 UTC 2019
    ;; MSG SIZE  rcvd: 44

    Dans la "SECTION ANSWER", vous verrez un enregistrement A pour mysql qui se résout en 172.23.0.2 (votre adresse IP aura très probablement une valeur différente). Bien que mysql ne soit normalement pas un nom d'hôte valide, Docker a pu le résoudre en l'adresse IP du conteneur qui avait cet alias de réseau. Rappelez-vous, vous avez utilisé le --network-alias plus tôt.

    Ce que cela signifie, c'est que votre application doit simplement se connecter à un hôte nommé mysql et elle parlera à la base de données.

Exécuter votre application avec MySQL

L'application todo supporte la définition de quelques variables d'environnement pour spécifier les paramètres de connexion MySQL. Elles sont :

  • MYSQL_HOST - le nom d'hôte pour le serveur MySQL en cours d'exécution
  • MYSQL_USER - le nom d'utilisateur à utiliser pour la connexion
  • MYSQL_PASSWORD - le mot de passe à utiliser pour la connexion
  • MYSQL_DB - la base de données à utiliser une fois connecté
Note

Bien que l'utilisation de variables d'environnement pour définir les paramètres de connexion soit généralement acceptée pour le développement, c'est fortement déconseillé lors de l'exécution d'applications en production. Diogo Monica, un ancien responsable de la sécurité chez Docker, a écrit un excellent article de blog expliquant pourquoi.

Un mécanisme plus sécurisé est d'utiliser le support des secrets fourni par votre framework d'orchestration de conteneurs. Dans la plupart des cas, ces secrets sont montés comme fichiers dans le conteneur en cours d'exécution. Vous verrez de nombreuses applications (y compris l'image MySQL et l'application todo) supporter aussi les variables d'environnement avec un suffixe _FILE pour pointer vers un fichier contenant la variable.

Par exemple, définir la variable MYSQL_PASSWORD_FILE fera que l'application utilise le contenu du fichier référencé comme mot de passe de connexion. Docker ne fait rien pour supporter ces variables d'environnement. Votre application devra savoir chercher la variable et obtenir le contenu du fichier.

Vous pouvez maintenant démarrer votre conteneur prêt pour le développement.

  1. Spécifiez chacune des variables d'environnement précédentes, ainsi que connecter le conteneur à votre réseau d'application. Assurez-vous d'être dans le répertoire getting-started-app quand vous exécutez cette commande.

    $ docker run -dp 127.0.0.1:3000:3000 \
      -w /app -v "$(pwd):/app" \
      --network todo-app \
      -e MYSQL_HOST=mysql \
      -e MYSQL_USER=root \
      -e MYSQL_PASSWORD=secret \
      -e MYSQL_DB=todos \
      node:18-alpine \
      sh -c "yarn install && yarn run dev"
    

    Dans Windows, exécutez cette commande dans PowerShell.

    $ docker run -dp 127.0.0.1:3000:3000 `
      -w /app -v "$(pwd):/app" `
      --network todo-app `
      -e MYSQL_HOST=mysql `
      -e MYSQL_USER=root `
      -e MYSQL_PASSWORD=secret `
      -e MYSQL_DB=todos `
      node:18-alpine `
      sh -c "yarn install && yarn run dev"

    Dans Windows, exécutez cette commande dans l'invite de commande.

    $ docker run -dp 127.0.0.1:3000:3000 ^
      -w /app -v "%cd%:/app" ^
      --network todo-app ^
      -e MYSQL_HOST=mysql ^
      -e MYSQL_USER=root ^
      -e MYSQL_PASSWORD=secret ^
      -e MYSQL_DB=todos ^
      node:18-alpine ^
      sh -c "yarn install && yarn run dev"
    
    $ docker run -dp 127.0.0.1:3000:3000 \
      -w //app -v "/$(pwd):/app" \
      --network todo-app \
      -e MYSQL_HOST=mysql \
      -e MYSQL_USER=root \
      -e MYSQL_PASSWORD=secret \
      -e MYSQL_DB=todos \
      node:18-alpine \
      sh -c "yarn install && yarn run dev"
    
  2. Si vous regardez les journaux pour le conteneur (docker logs -f <container-id>), vous devriez voir un message similaire au suivant, qui indique qu'il utilise la base de données mysql.

    $ nodemon src/index.js
    [nodemon] 2.0.20
    [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. Ouvrez l'application dans votre navigateur et ajoutez quelques éléments à votre liste de tâches.

  4. Connectez-vous à la base de données mysql et prouvez que les éléments sont écrits dans la base de données. Rappelez-vous, le mot de passe est secret.

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

    Et dans le shell mysql, exécutez ce qui suit :

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

    Votre table aura l'air différente car elle a vos éléments. Mais, vous devriez les voir stockés là.

Résumé

À ce stade, vous avez une application qui stocke maintenant ses données dans une base de données externe s'exécutant dans un conteneur séparé. Vous avez appris un peu sur le réseau de conteneurs et la découverte de services en utilisant DNS.

Informations connexes :

Étapes suivantes

Il y a de bonnes chances que vous commenciez à vous sentir un peu dépassé par tout ce que vous devez faire pour démarrer cette application. Vous devez créer un réseau, démarrer des conteneurs, spécifier toutes les variables d'environnement, exposer des ports, et plus. C'est beaucoup à retenir et cela rend certainement les choses plus difficiles à transmettre à quelqu'un d'autre.

Dans la section suivante, vous apprendrez Docker Compose. Avec Docker Compose, vous pouvez partager vos piles d'applications d'une manière beaucoup plus facile et laisser d'autres les faire tourner avec une seule commande simple.