Docker-compose, un outil pour déployer plusieurs conteneurs en même temps
Docker-Compose permet d'orchestrer vos conteneurs en tant que services, et ainsi de simplifier vos déploiements sur de multiples environnements.
Qu'est-ce que Docker-compose et à quoi ça sert ? La documentation officielle nous dit ceci :
Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration
En gros, il faut retenir que Docker-compose permet de gérer un ensemble de conteneurs (services) Docker au sein d'un même fichier de configuration (fichier YAML). Cela permet de gérer ce stack (cet ensemble de conteneurs, services) de manières centralisée.
Pour appréhender dans les faits cette notion, prenons l'exemple de la mise en place d'un blog reposant sur la solution Ghost.
Ce dernier repose sur une base de données, un peu de réseau, des données de configuration ... Tous ces éléments sont intégrables dans un ou plusieurs conteneurs.
Nous allons regrouper dans un fichier unique docker-compose.yml l'ensemble des services dont nous avons besoin.
Guillaume vous a présenté dans un précédent article la gestion des conteneurs Docker et des stacks (équivalent à docker-compose) via l'outil portainer.io :
De mon côté, je vais essayer de dégrossir la gestion des stacks en ligne de commande cette fois.
Pourquoi passer en CLI (command line interface) ? :
- Pour comprendre un peu mieux le moteur qui se cache dernière.
- Pour utiliser son propre EDI (éditeur de développement intégré, connu sous le nom d'IDE en anglais) : vi, Notepad++, Visual Studio Code, Eclipse ...
- Pallier aux limitations de portainer.io, qui est actuellement limité à la version 2.4 de docker-compose alors que la dernière version disponible et recommandée est la 3.8.
- Parce que je le vaux bien.
Mais avant tout ceci, nous allons revoir les bonnes pratiques :
- Les prérequis
- Installation de docker
- Installation de docker-compose
- Préparation de l'environnement de travail
Les prérequis
- Disposer d'un serveur
Un Nuc, un NAS, un Raspberry Pi, un ordinateur portable recyclé, tous peuvent servir d'hôte Docker. Mais attention, les NAS peuvent être cantonnés à des versions de docker pas forcément à jour ou avec limitation, un Raspberry Pi pourrait rencontrer des limitations en fonction de la charge CPU et/ou mémoire, voire d'espace disque... Vous l'avez compris, je ne suis pas sur ce type de composant, j'utilise un HPE ProLiant MicroServer Gen8 avec ESXi et des VMs, dont plusieurs hébergent Docker.
Mais le choix d'un NUC est également une très bonne solution. Vous aurez le choix d'installer l'OS hôte directement sur ce dernier ou un hyperviseur qui fera tourner, entre autres, votre hôte Docker. Un conseil, l'usage d'un Nuc avec VMware nécessite de valider avant achat sa compatibilité avec ESXi et en préférant une version récente (Google est votre ami pour ça). Guillaume utilise d'ailleurs un Nuc Intel en tant qu'hôte Docker, sans hyperviseur. - Le choix de l'OS hôte
Il y a des tonnes de solutions : Windows/Linux/Mac OS, mais aussi des distributions dédiées et optimisées pour Docker ou autres moteurs de conteneurisation. Après plusieurs essais de distributions, je vous conseille d'utiliser la distribution sur laquelle vous avez vos habitudes. Personnellement, il s'agit de Debian. Quand on voit l'orientation de certaines distributions dédiées rachetée par Red Hat, ne perdez pas de temps :). - Le choix de l'EDI
Là, comme pour l'OS, gardez vos habitudes. La base, c'est vi ou nano. Mais le confort d'un EDI est appréciable. Je verrais plus tard et si cela en intéresse certains pour vous présenter l'usage de Visual Studio Code, que j'apprécie pour la gestion des fichiers à distance, la mise en forme du code selon le langage utilisé (yml, toml, json...), la gestion intégrée de Docker, l'intégration de terminaux SSH ... - Comme toujours, un peu d'envie, beaucoup de curiosité et de la persévérance. Vous en serez récompensé.
Installation de Docker
Maintenant que nous avons mis au clair ce dont vous avez besoin pour utiliser Docker et Docker-compose dans de bonnes conditions, passons à l'installation.
Guillaume a déjà abordé l'installation de Docker et les commandes de base, indispensables. N'oubliez pas de suivre les étapes de post-installation !
Installation de Docker-Compose
Comme pour l'installation de Docker, l'installation de docker-compose doit s'appuyer sur la documentation officielle. Attention à bien cliquer sur le bon onglet ("Linux" dans notre cas) dans la section "Install Compose" pour disposer de la procédure adaptée.
Si vous n'y arrivez pas à l'aide de la documentation officielle de l'éditeur, il s'offre deux choix à vous :
- Arrêter tout de suite et trouver un autre loisir.
- Trouver sur le net un article (il y en a des tonnes) pour vous aider. Malheureusement, certains ne sont pas à jour, voire erronés.
Préparation de l'environnement
Votre hôte Docker est prêt, vous avez sous la main votre éditeur préféré, alors par où commencer ?
Par structurer vos dossiers, car cela peut très vite devenir le souk.
Le fichier de définition de votre stack Docker doit se nommer docker-compose.yml et être placé dans un dossier propre à la stack que nous voulons créer et gérer.
Et donc, comment organiser tout cela ? Il faut se demander comment organiser vos répertoires de configuration et des données persistantes si vous n'utilisez pas les volumes docker.
Il faut structurer l'arborescence des répertoires qui hébergeront les différents types de fichiers de votre stack.
Dans l'exemple ci-dessus, une arborescence pouvant être mise en place, à savoir un répertoire docker dans le répertoire d'accueil (home directory) de votre utilisateur et ensuite une séparation des dossiers contenants vos stacks docker-compose en fonction de vos besoins.
Ayant la nécessité de séparer les environnements productifs et de tests, j'ai un dossier prod et dev qui hébergent respectivement les différentes stacks. Mais faîtes comme cela vous arrange, l'objectif est d'éviter l'anarchie.
La structure du fichier docker-compose.yml
Nous allons prendre pour exemple principal une partie du stack MQTT composé de plusieurs services (le broker mqtt, zigbee2mqtt, ...). Guillaume vous présentant ses stacks, je ne reviendrais pas en détails sur cet exemple, mais vais plutôt vous évoquer les bonnes pratiques à suivre.
Le fichier docker-compose.yml est écrit en YAML, un langage verbeux permettant d'écrire de manière compréhensible des instructions dans un fichier. Pour en apprendre un peu plus sur ce langage, on vous redirige vers cet article, générique mais qui en présente tous les aspects.
Parmi les notions importants d'un fichier YAML, celui-ci est soumis à l'indentation (rien à voir avec la dentition) avec des espaces. Pour cela, je vous conseille d'utiliser un éditeur qui gère le langage yml (yaml), ce qui en facilite la lecture.
Il est recommandé de documenter votre stack, en y ajoutant des commentaires (avec la source des images utilisées, les commandes à utiliser en prérequis comme la création de répertoires, le positionnement de droits spécifiques, ...). Pour ajouter un commentaire, il suffit de commencer la ligne par un #
.
En ligne 1, nous donnons une description de notre stack :
# Stack QUALIF MQTT
En ligne 5 se trouve la définition des réseaux utilisés :
networks:
# traefik:
# external: true
lan:
external: true
# private:
# external: false
Pour démontrer l'indentation, une copie d'écran dans Visual Studio Code montre que la section "networks:" est constituée de trois réseaux, mais 2 sont commentés et réduits à l'affichage (cela permet de clarifier la lecture de fichiers complexes et de valider la bonne indentation).
Même principe dans la section services:
Développement du service "mqttx" :
Désolé d'avoir passé un peu de temps sur ces notions de mise en forme, mais elles sont indispensables à la bonne lecture et compréhension de votre stack, ainsi que pour éviter des erreurs. Une mauvaise indentation entrainera des erreurs au chargement de votre stack.
Vous pouvez constater dans l'exemple utilisé la présence de variables $MQTT_X, $DOMOXDIR ... . Nous verrons dans un prochain article la notion des variables externes dans un fichier dédié (.env), ainsi que les secrets, qui contribuent à la bonne gestion de l'environnement de vos containers et à l'amélioration de la sécurité de votre hôte et ses conteneurs.
Les commandes de base Docker-Compose
Guillaume vous a présenté les commandes de base de Docker, je vais vous lister ci-dessous quelques commandes utiles pour docker-compose :
- Pour démarrer votre stack, sachant qu'il faut être dans le répertoire où se trouve le fichier docker-compose.yml :
docker-compose up
- Pour que la stack soit exécutée en tâche de fond et vous rende la main sur la console, il faut ajouter "-d" à la suite de votre commande :
docker-compose up -d
- Pour lister l'ensemble des services de votre stack :
docker-compose ps
L'avantage par rapport à la commande docker ps
, c'est que seuls les services de votre stack sont listés et non l'ensemble des conteneurs qui tournent sur votre hôte Docker.
- Les commandes d'arrêt et de démarrage des conteneurs de la stack :
docker-compose stop
docker-compose start
- L'arrêt ou le démarrage d'un service (conteneur) de votre stack :
docker-compose stop eclipse-mosquitto
docker-compose start eclipse-mosquitto
- Pour supprimer tous les containers, réseaux, volumes, images de votre stack :
docker-compose down
Pour recréer votre stack, on relance la commande "docker-compose up -d"
- Pour lister les processus de vos services :
docker-compose top
Je vous laisse prendre connaissance de l'ensemble des commandes disponibles pour docker-compose :
Commands:
build Build or rebuild services
config Validate and view the Compose file
create Create services
down Stop and remove containers, networks, images, and volumes
events Receive real time events from containers
exec Execute a command in a running container
help Get help on a command
images List images
kill Kill containers
logs View output from containers
pause Pause services
port Print the public port for a port binding
ps List containers
pull Pull service images
push Push service images
restart Restart services
rm Remove stopped containers
run Run a one-off command
scale Set number of containers for a service
start Start services
stop Stop services
top Display the running processes
unpause Unpause services
up Create and start containers
version Show version information and quit
- Pour avoir de l'aide sur une commande, et notamment voir toutes les options disponibles, n'hésitez pas à utiliser :
docker-compose help 'commande'
Ce qui donne par exemple pour la commande up
:
exploit@docker-01:~/docker/domopi$ docker-compose help up
Usage: up [options] [--scale SERVICE=NUM...] [--] [SERVICE...]
Options:
-d, --detach Detached mode: Run containers in the background,
print new container names. Incompatible with
--abort-on-container-exit.
--no-color Produce monochrome output.
--quiet-pull Pull without printing progress information
--no-deps Don't start linked services.
--force-recreate Recreate containers even if their configuration
and image haven't changed.
--always-recreate-deps Recreate dependent containers.
Incompatible with --no-recreate.
--no-recreate If containers already exist, don't recreate
them. Incompatible with --force-recreate and -V.
--no-build Don't build an image, even if it's missing.
--no-start Don't start the services after creating them.
--build Build images before starting containers.
--abort-on-container-exit Stops all containers if any container was
stopped. Incompatible with -d.
--attach-dependencies Attach to dependent containers.
-t, --timeout TIMEOUT Use this timeout in seconds for container
shutdown when attached or when containers are
already running. (default: 10)
-V, --renew-anon-volumes Recreate anonymous volumes instead of retrieving
data from the previous containers.
--remove-orphans Remove containers for services not defined
in the Compose file.
--exit-code-from SERVICE Return the exit code of the selected service
container. Implies --abort-on-container-exit.
--scale SERVICE=NUM Scale SERVICE to NUM instances. Overrides the
`scale` setting in the Compose file if present.
Mot de la fin
Il est probable que suite à l'application des tutoriaux de ce blog ou d'autres, vous ayez déjà connaissance d'une partie des informations présentées dans cet article.
Mais au regard des questions qui nous sont posées, il semblait utile de faire un article sur ces principes de base qui peuvent pour les plus aguerris n'être qu'un simple rappel, mais bienfaisants pour les plus novices d'entre vous.
Passer par la ligne de commande n'est pas une tare, bien au contraire, et vous permettra une meilleure compréhension et facilitera le diagnostique.
N'hésitez pas à laisser un commentaire si cet article vous a plu ou si vous avez une question à propos de l'installation ou l'utilisation de Docker-Compose pour gérer vos services Docker. Nous vous invitons également à nous rejoindre sur notre groupe Telegram. Merci pour votre lecture !