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.


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.
-
Créez le réseau.
$ docker network create todo-app
-
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.TipVous 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 commandedocker volume create
. Docker reconnaît que vous voulez utiliser un volume nommé et en crée un automatiquement pour vous. -
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éestodos
.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)
-
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.
-
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
-
À 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ôtemysql
.$ 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
pourmysql
qui se résout en172.23.0.2
(votre adresse IP aura très probablement une valeur différente). Bien quemysql
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écutionMYSQL_USER
- le nom d'utilisateur à utiliser pour la connexionMYSQL_PASSWORD
- le mot de passe à utiliser pour la connexionMYSQL_DB
- la base de données à utiliser une fois connecté
NoteBien 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.
-
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"
-
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
-
Ouvrez l'application dans votre navigateur et ajoutez quelques éléments à votre liste de tâches.
-
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.