3.6. Docker-compose
Bien que Docker possède des commandes efficaces et claires, l’exemple illustratif utilisé au fil des pages précédentes a mis en évidence qu’une application un minimum complexe nécessitait assez vite de nombreuses lignes de commandes riches en options. Bien que certaines d’entre elles puissent être “remontées” dans les Dockerfiles, ce n’est pas le cas de toutes. En effet, un Dockerfile regroupe les paramètres et spécificités d’une image destinée à tourner dans des environnements multiples. Certains paramètres, tels que les bind mounts ou la publication de ports, sont spécifiques à l’hôte sur lesquel l’application est lancée. De plus, un Dockerfile définit un container unique, sans tenir compte d’éventuelles interactions avec d’autres containers.
Pour permettre la gestion unifiée et simplifiée d’applications multi-containers, Docker offre une couche de gestion supplémentaire, via l’outil “Docker Compose” [1,2]. Cet outil, toujours basé sur le principe de l’Infrastructure as Code, permet de définir dans un seul fichier tous les paramètres nécessaires au lancement d’une application multi-containers sur un hôte unique (un orchestrateur sera nécessaire pour les applications multi-hôtes).
Ensuite, au départ de ce fichier Docker Compose, une seule commande suffit pour lancer tous les containers nécessaires et leurs “dépendances” (volumes, réseau).
Reprenons notre exemple, et les lignes de commandes que nous avions identifiées :
<figcaption>
docker volume create db-vol
docker network create net
docker run -d \
--name web \
-p 3000:80 \
--mount type=bind,source="$(pwd)"/src,target=/app \
--network=net
nginx
docker run -d \
--name db \
--mount source=db-vol,target=/var/lib/mysql \
--network=net \
mysql
Ces lignes de commandes Docker font les tâches suivantes :
- Créer un volume
- Créer un réseau
- Créer un container web avec publication de port, bind mount et association au réseau net
- Créer un container db avec liaison au volume et au réseau net
Nous allons créer un fichier docker-compose.yml (au format YAML), reprenant toutes ces fonctionnalités :
version: "3"
name: app-web-exemple
services:
web:
image: nginx
ports:
- 3000:80
networks:
- net
volumes:
- ./src:/app
db:
image: mysql
volumes:
- db-data:/var/lib/mysql
networks:
- net
environment:
- MYSQL_ROOT_PASSWORD=my-secure-pwd
volumes:
db-data:
networks:
net:
Quelques précisions au sujet de ce fichier :
- Trois types d’objets ont été définis : les volumes, les networks et les services. Les deux premiers correspondent aux objets Docker déjà vus. Le troisième type, les services, définit les différents containers liés à l’application et leur agencement. Chaque “service” a un nom, qui sera utilisé pour identifier l’objet Docker, conjointement avec le nom de l’application définie en haut du fichier docker-compose. Ici, nous avons un service web et un service db, définis avec les volumes et réseaux associés.
- La clé “volumes” est utilisée aussi bien pour les bind mounts que pour les volumes nommés. Dans le premier cas, c’est un chemin qui est indiqué comme élément source, tandis que dans le second cas, il s’agit du nom du volume correspondant. Ce volume se retrouve également défini globalement plus bas.
- Pour chaque service, on définit l’image dont il sera issu. On peut soit utiliser une image toute faite, soit spécifier qu’il faut construire l’image depuis un Dockerfile.
- Pour le service “db”, on a également défini une variable d’environnement indiquant le mot de passe root à configurer. Notez qu’on évite en général de mettre des mots de passe dans les fichiers Docker, ainsi que dans les variables d’environnement, cela constitue des failles de sécurité. D’autres mécanismes existent pour gérer ça de manière plus sécurisée. On peut par exemple stocker le mot de passe de mysql dans un fichier de mot de passe, et utiliser la variable d’environnement MY_SQL_ROOT_PASSWORD_FILE, ou bien encore utiliser les Docker Secrets [3,4], qui sont au départ uniquement accessibles lors de l’utilisation de l’orchestrateur Docker Swarm, mais qui peuvent malgré tout être exploités dans Docker Compose.
Nous allons à présent lancer l’application. Pour cela, on utilise la commande “docker compose up” (l’option -d permet de ne pas avoir les logs dans la console, ce qui est plus clair pour la démo).
<figcaption>
Lors de la première exécution, Docker Compose peut, le cas échéant, aller chercher (ou construire) les images manquantes. Lors des exécutions suivantes, il se chargera de ne télécharger et/ou lancer que les objets qui ne sont pas encore disponibles ou pas encore lancés.
Dans ce cas-ci, on observe que quatre objets sont créés : deux containers, un volume et un réseau, ce qui correspond à ce qui avait été défini dans le fichier docker-compose.
Après lancement, on peut vérifier que les containers sont bien lancés : Ils apparaissent lors d’un “docker container ls”, avec des noms dérivés du nom de l’application et des noms des services. On voit que le port 80 du container du serveur Web est bien publié sur le port 3000 de l’hôte
Le réseau a également bien été créé, et un “docker network inspect” nous renseigne sur les IPs des deux containers. On retrouve également bien trace du volume, en faisant un “docker volume ls”. Le réseau et le volume sont également nommés d’après le nom de l’application.
Enfin, l’utilisation du navigateur en ligne de commande “lynx” nous permet de vérifier que l’application est bien disponible sur le port 3000 de l’hôte.
Pour stopper l’application, il suffit simplement de taper “docker compose down” : tous les containers seront arrêtés et supprimés, ainsi que le réseau. Par contre, le volume reste quant à lui présent sur le système, afin d’éviter les pertes de données critiques. Il sera ré-utilisé le cas échéant lors des lancements ultérieurs de l’application.
Bibliographie
[1] Documentation Docker, Try Docker Compose, consulté le 20 février 2023
[2] Documentation Docker, Key Features and use cases of Docker Compose, consulté le 20 février 2023
[3] Documentation Docker Swarm, Manage Sensitive Data with Docker Secrets, consulté le 20 février 2023
[4] Documentation Docker Compose, Secrets Top Level Element, consulté le 20 février 2023