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.

Docker-compose, un outil pour déployer plusieurs conteneurs en même temps

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 :

Améliorer la gestion de vos containers Docker avec Portainer
Après les 2 articles vous permettant de vous familiariser avec Docker et sescontainers (Bitwarden[/bitwarden-le-gestionnaire-de-mots-de-passe-montant-presentation-et-installation/] pour le premier, et l’automatisation du téléchargement de vos séries et films[/initiation-a-docker-sur-synology-et-…

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.
Pour ceux qui gèrent déjà leurs conteneurs en ligne de commande avec docker-compose, cet article ne devrait rien vous apprendre de nouveau. Il peut quand même être utile pour vous rappeler quelques bonnes pratiques.

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 !

Docker, Build, Ship and Run Any App, Anywhere
Docker [https://www.docker.com/], si vous n’en avez jamais entendu parler (cequi n’est pas possible si vous lisez mon blog !), est un logiciel open sourcepermettant d’embarquer une application dans un ou plusieurs conteneurslogiciels, qui pourra s’exécuter sur n’importe quel serveur, qu’il soit p…

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.

Install Docker Compose
How to install Docker Compose

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
Attention ! Si vos données ne sont pas persistantes, elles seront supprimées..

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 !