« Docker Compose » est un outil permettant de définir et d’exécuter, sous forme de services, des applications Docker à conteneurs multiples. Il sera donc possible en utilisant « Docker Compose » de définir des applications utilisant plusieurs conteneurs ainsi que leurs configurations, comme par exemple l’image utilisée, le port ou les réseaux à utiliser, les volumes, les dépendances des applications, etc.
« Docker Compose » va permettre également de créer des « stack », c’est-à-dire de créer des applications multi-conteneurs et « clusterisées ».
Avec « Docker Compose », vous utilisez un fichier YAML pour configurer les services de votre application. Ensuite, avec une seule commande, vous créez et démarrez tous les services de votre configuration.
« Docker Compose » possède également des commandes pour gérer le cycle de vie des applications permettant de :
Si vous avez installé docker via « Docker-Toolbox » ou « Docker Desktop pour Windows », dans ce cas « Docker Compose » est déjà installé et fonctionnel.
Dans le cas contraire il sera possible de l’installer à la main en le téléchargeant depuis le GitHub officiel à cette adresse :
https://github.com/docker/compose/releases/latest
Contrairement à Windows, Compose n’est pas compris dans les fichiers d’installation de Docker Engine ou Docker Machine.
Il faudra l’installer soit même afin de s’en servir.
Dans un premier temps nous allons nous rendre à cette adresse afin de connaître la version de la dernière release :
https://github.com/docker/compose/releases/latest
En suite pour télécharger « Docker Compose », il faudra utiliser la commande suivante :
curl -L "https://github.com/docker/compose/releases/download/"Numero_de_version"/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Une fois téléchargé, il faudra ajouter des droits d’exécution au binaire à l’aide de la commande
chmod +x /usr/local/bin/docker-compose
Nous pouvons vérifier si tout fonctionne à l’aide de la commande suivante :
docker-compose version
Normalement tout devrai être fonctionnel et la version de Docker Compose que nous venons d’installer (1.24.1 au moment d la rédaction de cette documentation) devrait être visible à l’écran
Comme de nombreuses commandes, « docker-compose » possèdes différentes options que voici :
docker-compose up "options" "nom_du_service"
Construit, crée ou recrée, démarre et attache des conteneurs. À moins qu'ils ne soient déjà en cours d'exécution, cette commande démarre également les services liés.
Options :
Arrête les conteneurs en cours d'exécution sans les enlever. Ils peuvent être redémarrés avec « docker-compose start ».
docker-compose stop "options" "nom_du_service"
Options:
Démarre les conteneurs existants ainsi que leurs services.
docker-compose start "nom_du_service"
Redémarre tous les services arrêtés et en cours d'exécution.
Si vous apportez des modifications à votre configuration « docker-compose.yml », ces modifications ne sont pas prises en compte après l'exécution de cette commande.
Par exemple, les modifications apportées aux variables d’environnement (qui sont ajoutées après la création d’un conteneur, mais avant l’exécution de la commande du conteneur) ne sont pas mises à jour après le redémarrage.
docker-compose restart "options" "nom_du_service"
Options:
Supprime les conteneurs de service arrêtés.
Par défaut, les volumes anonymes attachés aux conteneurs ne sont pas supprimés. Vous pouvez remplacer ceci avec « -v ».
Pour répertorier tous les volumes, utilisez la commande « docker volume ls ».
Attention : Toutes les données qui ne sont pas dans un volume sont perdues.
docker-compose rm "options" "nom_du_service"
Options:
Force les conteneurs en cours d'exécution à s'arrêter en envoyant un signal « SIGKILL ».
Cette manière d’arrêter les conteneurs n’est pas recommandée car elle est comparable au fait de débrancher électriquement un ordinateur (ce n’est jamais une bonne chose).
docker-compose kill "options" "nom_du_service"
Arrête les conteneurs, les supprime mais supprime également les réseaux, les volumes et les images créés par « up ».
Par défaut, les seules choses supprimées sont:
docker-compose down "options"
Options:
Afficher les informations de version de Docker-Compose
docker-compose version
Affiche la liste des conteneurs
docker-compose ps
Options:
Vérifie, validez et affichez le fichier « .yml ».
docker-compose config "options"
Options:
Liste les images utilisées par les conteneurs créés.
docker-compose images "options"
Options:
Affiche les processus en cours.
docker-compose top
Cette commande est l'équivalent de « docker exec ».
Avec cette sous-commande, vous pouvez exécuter des commandes arbitraires dans vos services. Les commandes allouent par défaut un TTY.
docker-compose exec "options" "-e KEY=VAL" "nom_du_service" "commande" "arguments"
Options:
Met en pause les conteneurs d'un service.
docker-compose pause "nom_du_service"
Annule la mise en pause des conteneurs d'un service.
docker-compose unpause "nom_du_service"
Affiche les logs des services.
docker-compose logs "options" "nom_du_service"
Options:
Pousse les images des services dans leur registre / référentiel respectif.
Les hypothèses suivantes sont faites:
docker-compose push "options" "nom_du_service"
Options:
Extrait une image associée à un service défini dans un fichier « docker-compose.yml » ou « docker-stack.yml », mais ne démarre pas les conteneurs basés sur ces images.
docker-compose pull "options" "nom_du_service"
Options:
Affiche le port public pour un mappage de port.
docker-compose port "options" "nom_du_service" "Numéro_du_port_privé"
Options:
Affiche les « events » de conteneur pour chaque conteneur du projet.
docker-compose events "options" "nom_du_service"
Options:
Avec l’option « --json », un objet json est imprimé un par ligne au format suivant :
Afin d’illustrer «le fonctionnement de « Docker Compose » nous allons directement commencer par l’utiliser.
Dans un premier temps, nous allons créer un répertoire. En effet à l’aide de « Docker Compose » il est possible d’avoir plusieurs services qui tournent. Chacun de ces services est « contextuel » au répertoire dans lequel il se trouve.
mkdir app-docker-compose
Ensuite nous entrons dans ce répertoire afin d’y créer le service
cd app-docker-compose
Attention le service devra obligatoirement comprendre un morceau du nom du répertoire
Pour créer le service nous utiliserons un fichier « docker-compose.yml » qu’il faudra créer.
Prenons l’exemple de la création d’un service Web. Le contenu de notre fichier sera le suivant :
web:
container_name: serveur-web
image: nginx
Enregistrer le fichier et quitter.
Attention docker compose n’aime pas la tabulation, il n’y a pas de tab dans le fichier mais des espaces.
Mais que va faire ce fichier une fois lancé ?
Il va simplement créer un service appelé « web » dont le nom du conteneur sera « serveur-web » en utilisant l’image « nginx ».
Nous pouvons vérifier le fichier à l’aide de
docker-compose config
Ici nous ne précisons pas le fichier « .yml » à vérifier car il n’y en a qu’un seul dans le répertoire dans lequel nous sommes.
Nous pourrions avoir plusieurs répertoires avec un fichier « .yml » dans chacun d’entre eux, la commande « docker-compose config » ne vérifiera que le fichier du répertoire dans lequel nous sommes positionné, à savoir ici « app-docker-compose ».
Il n’y a pas d’erreur, le fichier est fonctionnel. On y retrouve les différentes informations qui vont composer le service ainsi que des lignes supplémentaires :
Pour lancer le service il suffira de taper la commande suivante à nouveau sans préciser de nom de fichier.
docker-compose up
Attention petite subtilité, comme il s’agit d’un serveur web nous ajouterons l’option « -d » à la fin de la commande comme nous l’avions fait avec le « docker run » dans la documentation « Docker - Chapitre 1 - Installation Et Administration »
Docker Compose a correctement créé le conteneur « serveur-web » avec la configuration qui était dans le fichier à savoir l’utilisation de l’image « nginx ».
Au même titre qu’avec la commande « docker ps » pour les conteneur, nous pouvons voir les services qui tournent en utilisant la commande suivante
docker-compose ps
Maintenant que le serveur Web est démarré, nous pouvons tenter de nous y connecter via le web.
Nous pouvons malheureusement constater que ça ne marche pas et que nous n’arrivons pas à afficher la page du serveur Web.
En effet, en utilisant la commande « docker-compose ps » nous pouvons voir que le port 80 est effectivement utilisé mais pour le conteneur.
Comme nous l’avons vu précédemment, pour se connecter à un conteneur il faudra passer par son hôte. Dans ce cas précis, qu’en est-il du port 80 de l’hôte, est-il fermé ou est-il déjà utilisé par un autre serveur ?
Pour résoudre ce problème il suffira d’effectuer à nouveau une redirection de port, comme nous l’avons déjà vu.
Cependant nous l’effectuerons directement depuis les informations du fichier « .yml »
Commençons par stopper le service Web en utilisant la commande
docker-compose stop
Puis supprimons le serveur avec la commande
docker-compose rm
Maintenant ajoutons la redirection de port dans le fichier « .yml »
Vérifions encore la configuration du fichier
Comme nous avons supprimé le conteneur, nous allons le recréer à l’aide de la commande utilisée précédemment
docker-compose up -d
Essayons de nouveau de nous connecter mais cette fois ci en précisant le port 8000 qui est celui enregistré dans le fichier « .yml »
Tout fonctionne et la page par défaut du serveur Nginx est visible.
Cependant, lors de la vérification de la configuration du fichier « .yml » nous avons pu constater l’ajout de lignes supplémentaires.
A quoi correspondent ces lignes :
Voici la liste officielles des différentes versions possibles au moment de l’écriture de cette documentation
Que se passe-t-il lorsque ces informations sont rajoutées dans le fichier « .yml » et que nous relançons la commande de vérification de la configuration de ce fichier ?
docker-compose config
La configuration est correcte toutefois la ligne « network_mode: Bridge » n’est plus présente.
Encore une fois recréons notre conteneur pour le serveur Web.
Cette fois-ci nous pouvons constater la création d’un nouveau Network en mode Bridge (celui par défaut) au nom de notre répertoire.
Il est d’ailleurs présent parmi la liste des différents network disponibles dans Docker
Pour vérifier la configuration de ce nouveau Network nous pourrons utiliser la commande « docker network inspect app-docker-compose_default » que nous avons vu précédemment.
Nous y retrouverons l’adresse du réseau ainsi que sa Gateway mais également l’adresse de notre conteneur « Serveur-Web »
Il sera d’ailleurs possible de ping le conteneur à cette adresse depuis notre hôte
Il faut savoir que si nous supprimons un service créé via docker-compose, le Network associé ne sera pas supprimé.
En effet, les réseaux créés de cette manière sont persistants et si l’on recréé une fois de plus le conteneur « Serveur-Web », il sera automatiquement ajouté dans ce réseau.
Passons maintenant à la configuration de notre fichier « .yml » pour qu’il propose plusieurs services.
En effet, en ayant déclaré l’option « services » dans notre fichier nous avons la possibilité d’en ajouter autant que nous voulons.
Pour cela nous effectuerons la modification suivante :
Notre fichier « .yml » propose donc deux services :
Vérifions la configuration du fichier :
Le fichier est correctement configuré nous allons donc effectuer à nouveau notre « up » via docker-compose
La création des deux conteneurs s’est bien passée nous allons refaire un « inspect » sur le custom Network via la commande « docker network inspect app-docker-compose_default »
Un seul de nos deux conteneur n’est présent dans ce custom Network. Que s’est-il passé ?
Pour savoir, vérifions leur état via « docker-compose ps »
Nous constatons que le serveur de base de données est en état « exit » et n’est donc plus démarré.
Pour savoir ce qu’il s’est passé, nous allons utiliser la commande suivante :
docker-compose logs
Le serveur MySQL ne s’est pas démarré car pour qu’il fonctionne il a besoin d’une configuration au niveau du password qui doit correspondre soit à :
Il va donc falloir rajouter cette information dans notre fichier « .yml » de la manière suivante :
Vérification de la configuration :
Il n’y a pas d’erreurs, tout à l’air de fonctionner.
Comme nous avons effectué une modification sur le service « db » et uniquement sur celui-ci il ne va pas être utile de supprimer les conteurs précédemment créés pour éviter les conflits de noms. En effet, notre service Web est toujours fonctionnel et en ligne mais le service de BDD n’a quant à lui pas démarré.
Nous allons donc utiliser une commande permettant de relancer uniquement ce dernier en prenant en compte les modifications apportées et sans dépendances :
docker-compose up -d --no-deps db
Nous pouvons vérifier s’il fonctionne :
Maintenant que nos deux services sont up nous allons à nouveau faire un inspect sur le custom Network « docker network inspect app-docker-compose_default »
Nous retrouvons effectivement ces deux conteneur dans notre custom Network.
L’avantage d’avoir ces deux services dans le même custom Network est qu’il sera possible d’exécuter des commandes depuis un conteneur vers un autre conteneur pour qu’ils communiquent ensemble.
Pour cela nous utiliserons la même option que nous avions découvert avec Docker Engine à savoir « exec ».
Pour rappel, « exec » est spécialement conçu pour exécuter de nouvelles commandes dans un conteneur déjà démarré, que ce soit un Shell ou un autre processus.
Par exemple si l’on souhaite que notre serveur web effectue un ping vers notre serveur BDD il faudra utiliser la commande suivante :
docker-compose exec "nom_du_conteneur_qui_va_exécuter_la_commande" "commande_à_exécuter" "conteneur_ciblé"
Nous pouvons effectivement voir la réponse au ping de notre serveur BDD, les deux conteneurs peuvent donc communiquer ensemble puisqu’ils sont dans le même custom Network.
Comme nous l’avions indiqué tout à l’heure, les custom Network sont persistants et le fait de supprimer les conteneurs qu’ils contiennent ne suffit pas pour les supprimer.
Cependant il existe une commande qui permet de stopper tous les services, de supprimer tous les conteneurs mais également le custom Network du fichier « .yml » correspondant au répertoire dans lequel vous êtes.
La commande est la suivante :
docker-compose down
Vérifions l’état de nos conteneurs :
Et vérifions les différents Network à notre disposition
Les conteneurs ainsi que le custom Network ont effectivement été supprimés.
Dans cette partie de la documentation, nous allons utiliser la création de l’image faite par un « Dockerfile » directement dans le « docker compose ». Si vous ne savez pas ce qu’est un « Dockerfile », il faudra revoir la première partie de la documentation sur Docker appelée « Docker - Chapitre 1 - Installation Et Administration ».
Pour commencer, nous allons créer un répertoire « ping » et dans ce répertoire nous allons créer un fichier « Dockerfile »
Ouvrir le fichier « Dockerfile » avec un éditeur de texte et y inscrire les informations suivantes :
Ce Dockerfile va permettre de créer une image et de lancer une commande de ping sur le localhost.
Le fichier « Dockerfile » étant prêt nous allons maintenant créer un fichier « docker compose », toujours dans le répertoire « ping » et l’éditer avec un éditeur de texte :
Ici, nous allons créer un service qui s’appelle « ping » et ‘image qui sera utilisée sera créée à l’aide du « build ».
Le « build » ira chercher notre fichier « Dockerfile », le fichier étant dans le même répertoire nous pouvons simplement mettre un « . ». Si le fichier « Dockerfile » n’était pas dans le même répertoire nous aurions pu mettre son chemin d’accès.
Tout est prêt nous pouvons maintenant lancer le « up » pour exécuter le fichier « docker compose ».
Lorsque l’on lance cette commande nous pouvons constater plusieurs choses :
Nous avons donc créer un fichier « docker compose » qui a utilisé un fichier « Dockerfile » pour créer une image et l’instancier.
Bien sûr, notre fichier « docker compose » était très basique car le but est de montrer le fonctionnement mais nous aurions pu y ajouter encore beaucoup d’autres informations qui auraient été exécutées lors de la commande « docker-compose up »
Nous pouvons également lister les images utilisées par docker-compose à l’aide de la commande
docker-compose images
On y retrouve notre conteneur « ping_ping1 » et l’image « ping_ping » qui a permis de créer le conteneur.
Nous pouvons donc effectuer un « docker compose » à partir d’une image que l’on aura construit par nous-même ou à partir d’un fichier « Dockerfile ».
Dans cette partie de la documentation, nous allons voir le fonctionnement des volumes avec « docker compose ».
Attention : Pour garder une trace des précédentes manipulation et des différents fichiers « docker-compose » que nous avons utilisé, je préfère créer un nouveau répertoire et y copier le fichier « docker-compose.yml » que nous avions vu en premier. Si vous le désirez, vous n’êtes pas obligé de le faire et il suffira simplement d’éditer à chaque fois le fichier « docker-compose.yml » en fonction des manipulations que nous faisons.
Nous allons maintenant éditer le fichier pour y laisser seulement le service web comme ceci :
On le lance à l’aide d’un docker compose up
docker-compose up -d
Nous pouvons vérifier le port utilisé à l’aide de la commande « ps »
docker-compose ps
Il s’agit bien du 8000 comme indiqué dans notre fichier.
Si l’on se connecte via un navigateur web à l’adresse IP de la machine et au port 8000 on pourra normalement voir la page d’accueil par défaut du serveur Nginx
http://192.168.189.158:8000
Le conteneur étant up il nous est possible de faire la commande « exec » pour y exécuter une commande.
docker-compose exec web bash
ici nous allons exécuter la commande bash ce qui va nous permettre d’avoir la main sur le conteneur
Maintenant que nous avons la main sur le conteneur nous pouvons y effectuer des commandes.
Par exemple nous allons faire la commande echo pour rediriger la sortie directement dans la page par défaut du serveur web
echo "Modification du serveur Web" > /usr/share/nginx/html/index.html
Si l’on retourne sur le navigateur nous pouvons voir que la page d’accueil a été modifiée.
Le problème est que cette modification est temporaire. Dès l’instant où le conteneur sera arrêté elles seront perdues.
docker-compose down
on redémarre le conteneur et on vérifie à nouveau la page web du serveur :
De la même manière que nous avions vu dans la première documentation sur Docker que nous pouvions utiliser des volumes pour rendre les données indépendantes de la vie du conteneur à l’aide de commandes, nous pourrons configurer le fichier « docker compose » pour préciser également le mappage d’un volume.
Pour cela nous allons commencer par créer un répertoire que nous appellerons « html » dans lequel nous allons créer un fichier « index.html »
Nous allons éditer ce fichier pour y mettre les informations que nous voulons.
Ensuite nous allons éditer notre fichier « docker compose » pour y ajouter les informations de mappage vers ce volume.
Ici nous allons rediriger le contenu de « volumes/html » vers « /usr/share/nginx/html »
On peut vérifier si la configuration est bonne avec « config »
docker-compose config
Pas de message d’erreur, tout devrait fonctionner.
On relance alors le conteneur avec un « up » et on vérifie la page web. Les modifications ont été faites et le volume fonctionne.
Le problème de ce que nous venons de voir est que pour l’instant, seul l’utilisateur en cours peut l’utiliser.
Si nous voulons faire en sorte que le volume soit utilisable par d’autres utilisateurs et d’autres conteneur il va falloir l’écrire différemment.
Ici, nous avons le service web dans lequel nous avons défini un volume que l’on a appelé « web-file » ainsi que le chemin vers lequel ce volume sera monté. Ce volume sera créé par « docker compose » et va nous permettre d’y mettre des fichiers.
Pour cela il faudra alors déclarer le volume de la même manière que nous avons déclaré le service.
Attention : le nom du volume déclaré doit correspondre au nom du volume écrit dans le service
Nous pouvons à nouveau vérifier la configuration avec « docker-compose config »
Tout à l’air correctement configuré.
Vérifions les volumes existant :
Pour l’instant nous n’avons pas de volume existant.
Lançons la création du service à l’aide de « docker compose »
docker-compose up -d
On peut également vérifier la création du service
Si l’on retourne sur le serveur web on pourra voir la page par défaut de nginx
Cependant, nous avons créé un volume que l’on peut retrouver à l’aide de la commande
docker volume ls
A ce stade, nous avons donc :
Pour avoir des informations sur le volume que l’on vient de créer nous allons utiliser la commande
docker volume inspect "nom_du_volume"
On y retrouvera toutes les informations concernant ce volume et notamment son point de montage sur notre machine.
C’est à partir de ce point de montage que nous allons pouvoir modifier les données qui seront utilisées par le service web.
A ce stade, le contenu de « /var/lib/docker/volumes/volumes_web-file/_data » appartient à root et les autres utilisateurs ne pourrons pas l’utiliser. Il faudra alors positionner les permissions voulues pour autoriser tous les utilisateurs ou seulement ceux désirés à utiliser ce volume (via des groupes par exemple).
Bien que ce ne soit pas le but premier de cette documentation, nous allons voir brièvement comment gérer les différents droits sur ces fichiers.
Dans un premier temps nous pouvons lister les droits actuellement positionnés
getfacl "cible"
Comme nous l’avons dit, root est le propriétaire et seul le groupe « root » ainsi que les utilisateurs qui en sont membres peuvent modifier le fichier.
Pour ajouter un groupe dans les permissions d’édition sur le fichier nous pouvons utiliser la commande suivante :
setfacl -m g:"nom_du_groupe":"permissions" "fichier"
Si l’on vérifie maintenant les différents droits nous pourrons voir que les membres du groupe « antoine » dont fait partie l’utilisateur antoine » possèdent des droits en lecture écriture exécution sur le fichier.
Revenons maintenant à la modification de la page d’accueil de notre serveur web.
Si l’on regarde le contenu du fichier « /var/lib/docker/volumes/volumes_web-file/_data/index.html » nous y retrouverons le contenu de la page d’accueil du serveur nginx.
Nous pouvons alors changer le contenu du fichier « index.html » pour y écrire ce que l’on veut puis enregistrer.
Une fois enregistré nous pouvons revenir sur la page web de notre serveur pour la rafraichir et vérifier si les modifications ont bien été prises en compte.
Comme les fichiers de configuration sont sauvegardés dans volume nous pouvons arrêter notre service web puis le relancer sans perte de données. Les modifications faites dans le fichier « index.html » seront conservées et de nouveau visibles sur la page du serveur web.
En effet, les modifications ne sont pas perdues car le volume en lui-même n’a pas été supprimé. Il est toujours présent dans « /var/lib/docker/volumes/ » sout le nom de « volumes_web-file ».
Cependant cette manipulation peut être dangereuse car si l’on utilise l’option « -v » lors d’un « docker-compose down », les volumes seront supprimés et leur données également.
Vérification de l’existence du volume
Toutes les modifications faites one été perdues
Il existe toutefois une possibilité pour éviter de perdre les données lorsque l’on arrête un service web en supprimant ses volumes.
Nous allons utiliser un montage NFS pour que cela fonctionne (si le service n’est pas installer il faudra le faire).
Pour cet exemple, nous allons dans un premier temps créer un répertoire appelé « nfs » dans « /root/app-docker-compose ».
Dans un second temps, nous allons créer un répertoire « files » dans « /root/app-docker-compose/nfs ».
Ensuite, nous allons copier le fichier « docker-compose.yml » se trouvant dans « volumes » dans le répertoire « /root/app-docker-compose/nfs » et lui permettre d’être exécuté.
Une fois la copie faite nous allons pouvoir entrer dans le répertoire « nfs » et modifier le fichier « docker-compose.yml » comme sur la capture suivante :
Ici, nous avons ajouté un « driver » et certaines options.
un « driver » permet de stocker des volumes sur un hôte en local ou à distance mais aussi via des fournisseurs de cloud pour crypter le contenu des volumes ou ajouter d'autres fonctionnalités.
Voici à quoi correspondent les lignes supplémentaires que nous avons ajouté :
Pour terminer, nous allons configurer le partage NFS dans le fichier « /etc/exports » comme ceci :
Redémarrer le service nfs :
Il ne reste plus qu’à utiliser « docker-compose » pour pouvoir créer notre conteneur avec le volume que l’on vient de configurer.
Le conteneur ainsi que le volume « nfs_Web-file » ont correctement été créés.
On peut d’ailleurs faire une vérification du contenu du répertoire « /root/app-docker-compose/nfs/files » afin de vérifier si les fichiers de notre service web y sont présent.
Nous pouvons également vérifier si le serveur web fonctionne en nous connectant à son IP depuis un navigateur web.
A ce stade, nous avons une configuration assez similaire à l’exemple précédent avec un volume créé et des fichiers qui n’appartiennent qu’à l’utilisateur root.
Pour que plusieurs utilisateurs puissent modifier ces fichiers nous allons à nouveau devoir positionner des droits UNIX sur le contenu du répertoire « files ».
Cette façon de faire permet de gérer les différents droits de manière beaucoup plus simple.
Comme dans l’exemple précédent, nous pouvons aussi modifier la page d’accueil de notre serveur web via le fichier « index.html ».
Vérification en rafraichissant la page web de notre serveur :
Mais au final quelle est la différence entre cet exemple et l’exemple précédent ?
L’intérêt du partage NFS est tout simplement le fait que lorsque l’on va supprimer le conteneur et son volume, les fichiers de configuration de notre serveur web ne seront pas supprimés.
Pour commencer on va vérifier les volumes présents :
Notre volume est présent nous pouvons maintenant passer à la suppression du conteneur et de son volume :
Attention : pour rappel l’option « -v » permet de supprimer les volumes et leur contenus.
Si l’on regarde à nouveau les volumes présents, il ne devrait plus y en avoir :
Vérifions si nos fichiers de configurations sont toujours présents dans le répertoire files :
Tout a fonctionné correctement. Nous avons créé un fichier « docker-compose » qui permet de mettre en place un conteneur avec un volume dont les données seront sur un partage NFS permettant ainsi de conserver les différents fichiers utiles à notre conteneur.
Toutes les personnes qui auront les droits d’exécution sur le fichier « docker-compose.yml » pourrons alors le relancer pour créer à nouveau un conteneur qui utilisera par défaut les fichiers sauvegardés.
Il en va de même pour les modifications qui pourront être apportées sur ces fichiers, toutes les personnes ayant les droits pourrons les modifier, impactant directement le conteneur.
Dans cette partie de la documentation nous allons nous intéresser aux réseaux avec « docker-compose ».
Pour cela, et comme pour les exemples précédents, nous allons directement voir ce que ça donne depuis un terminal.
Commençons par créer un nouveau répertoire appelé « réseaux » puis copions notre tout premier fichier « docker-compose.yml » dans ce répertoire afin de le modifier.
Nous allons donc le modifier comme ceci :
Nous allons également copier le fichier « dockerfile » qui se trouve dans le répertoire ping pour le mettre dans le répertoire réseau
Et nous allons le modifier comme ceci :
Attention : à titre d’information, je copie le fichier parce que je n’ai pas envie de tout réécrire 😉
Toujours dans le répertoire « reseaux »nous allons créer un fichier « entrypoint.sh » et le rendre exécutable.
Pour finir avec les préparations, nous allons éditer ce fichier pour qu’il contienne les informations suivantes :
Maintenant que les fichiers sont créés, nous avons :
Ce fichier va créer trois services appelés web, db et ping. Le service ping sera créé à partir d’un build et donc d’un fichier docker file
Ce fichier va permettre de créer une image et d’exécuter un script depuis cette dernière
Ce script sera utilisé par le service « ping » et va permettre de faire des ping sur les conteneurs des services « web » et « db », tant que la condition sera vraie. Du moins c’est ce qui devrai se passer.
Pour commencer nous allons effectuer le build de notre image
Puis nous allons vérifier si tout fonctionne nous allons effectuer la commande « docker-compose up »
La création des différents conteneurs fonctionne mais ce que l’on peut voir c’est que le ping lui ne marche pas.
Le message « ping_1 | ping: db: Name or service not known » est visible.
La raison est simple, nous avons créé des conteneurs et des actions à réaliser mais nous n’avons pas configuré de réseau entre eux.
En effet, les conteneurs étant isolés les uns des autres, pour que cela fonctionne nous allons devoir créer un réseau commun.
Pour créer un réseau nous pouvons directement passer par la modification de notre fichier « docker-compose ».
Il faudra cependant à nouveau activer la « version » du fichier « .yml » ainsi que les « services » comme nous le faisions précédemment.
Une fois le fichier modifié, nous allons à nouveau effectuer la commande « docker-compose ».
La première chose que nous allons constater est la création d’un réseau « défaut »
Une fois la création de ce réseau, nous allons constater que le ping fonctionne correctement.
Une fois les 5 ping effectués dans un sens comme dans l’autre, nous pourrons constater que nos conteneur sont arrêtés.
Nous pouvons également vérifier les différents réseaux disponibles et constater qu’un réseau a été créé.
Lorsque l’on active une version ainsi que les service, « docker-compose » va alors créer par défaut un réseau appelé « défaut ».
En plus de ce réseau nous aurons un DNS interne à docker, pour ce réseau, qui va alors permettre la résolution de nom de nos conteneurs afin qu’ils puissent communiquer ensemble.
Si l’on utilise la commande « docker network inspect » nous pourrons voir le détail de ce réseau y compris l’ip du réseau, son masque et sa passerelle.
Si l’on relance nos conteneurs avec la commande « docker-compose » mais que l’on utilise l’option « -d » pour que cette fois-ci ils ne s’arrêtent pas à la fin de l’exécution des ping, nous pourrons alors constater qu’ils font tous partis du réseau « reseau_default »
Vérification du réseau
Pour la suite de cet exemple, nous allons supprimer les conteneurs, les volumes ainsi que le réseau.
Le réseau ayant été également supprimé, si nous effectuons à nouveau un « inspect » dessus nous allons avoir une erreur puis qu’il n’existe pas. Il ne sera également plus dans la liste des réseaux disponibles.
Maintenant que nous avons vu la création du réseau par défaut et que nous avons supprimé les conteneurs, leur volumes ainsi que le réseau par défaut nous allons voir comment effectuer la création d’un réseau personnalisé.
Pour cela nous allons éditer le fichier « docker-compose.yml » et y ajouter les informations du réseau que l’on souhaite configurer et utiliser. Evidemment pour que les conteneurs soient dans le même réseau, il fut configurer le même pour chacun d’entre eux.
Ce que nous avons fait ici dans le fichier « yml » c’est :
Attention : Nous n’avons volontairement pas déclaré de réseau pour le service ping
On peut vérifier si la configuration est correcte avec la commande « docker-compose config ».
S’il n’y a pas de message d’erreur la configuration devrait être bonne.
Pour vérifier ça nous allons maintenant utiliser la commande « docker-compose up -d »
On remarquera tout de suite la création de deux réseaux :
Comme nous avons créé nos conteneurs en sous forme de service avec l’option « -d » nous ne pouvons pas voir le résultat de la commande ping. Cependant nous pouvons utiliser une commande que nous verrons plus en détail par la suite pour afficher ce qu’il se passe
docker-compose logs
Nous pouvons voir que le résultat de la commande ping utilisée par notre script est « ping_1 | ping: db: Name or service not known ».
Pourquoi ce résultat ? Tout simplement parce que les conteneurs « ping » et « web » / « db » ne sont pas dans les mêmes réseaux.
Comme nous n’avons pas déclaré de réseau spécifique pour le service « ping » et il s’est donc vu attribuer le réseau « default ».
A nouveau nous pouvons le vérifier via la commande « docker network inspect » sur les deux réseaux :
Pour effectuer la modification du réseau du service « ping », nous allons dans un premier temps devoir effectuer un nouveau « down -v » pour supprimer les conteneurs, leurs réseaux, etc
En suite dans un second temps nous allons éditer le fichier « yml » pour ajouter le réseau au service ping
On effectua à nouveau la commande « docker-compose up -d » pour relancer la création des conteurs.
Cette fois-ci un seul réseau a été créé et correspond effectivement à celui que nous avons déclaré.
Maintenant notre service « ping » devrait pouvoir communiquer avec les autres services du fichier et effectuer les pings demandés
Vérifions le résultat à l’aide de la commande suivante :
docker-compose logs
Vérifions le réseau « reseau-test » via un « inspect » :
Les trois conteneurs font bien partis de ce réseau et peuvent correctement communiquer entre eux.
Comme nous venons de le voir il est très facile de déclarer un réseau personnalisé pour nos conteneurs.
De la même manière il est possible de déclarer plusieurs réseaux à la fois.
Nous allons ici par exemple reprendre le fichier « docker-compose.yml » que nous venons de créer pour les réseaux et le modifier de sorte que le conteneur « web » soit dans le « reseau-web », le conteneur « db » soit dans le « reseau-db » et le conteneur « ping » soit dans les deux réseaux à la fois.
Pour cela nous allons donc modifier le fichier comme ceci :
Dans cette configuration, nos conteneurs « web » et « db » ne pourront pas communiquer ensemble tandis que le conteneur « ping » pourra communiquer avec chacun d’entre eux.
On peut revérifier la configuration avec la commande « docker-compose config » et s’il n’y a pas de message d’erreur, tout devrai fonctionner.
Il ne reste plus qu’à faire le « up » pour instancier les conteneurs et effectuer la création des réseaux.
Les deux réseaux sont maintenant dans la liste des réseaux disponibles
Et l’on peut vérifier le résultat des ping en utilisant à nouveau la commande « docker-compose logs »
Le ping fonctionne correctement car lors de la déclaration des deux réseaux sur le conteneur « ping », celui-ci s’est vu attribuer deux cartes réseaux.
Nous pouvons le vérifier en nous connectant au conteneur via la commande « exec »
Puis une fois que nous sommes connecté sur le conteneur nous allons installer les net-tools pour pouvoir afficher les cartes réseaux
Passons à l’affichage des cartes réseaux :
Le fait de pouvoir définir plusieurs réseaux dans un conteneur offre un grand nombre de possibilité, comme par exemple la création d’un routeur qui permettrait la communication entre différents réseaux de conteneurs.
Dans cette partie de la documentation, nous allons voir comment récupérer les logs via « docker-compose ».
Nous allons revenir dans le répertoire « app-docker-compose » pour y créer un nouveau sous répertoire appelé « logs » puis nous allons nous y déplacer pour créer un nouveau fichier « docker-compose.yml »
Editons le fichier pour avoir la configuration suivante Vérifions le contenu de ce fichier
Nous allons à présent instancier le conteneur
Puis vérifier si le conteneur est effectivement up
Maintenant que nous avons le conteneur pour le serveur web qui est up nous allons pouvoir utiliser la commande « logs » pour afficher certains logs de notre conteneur mais avant de commencer voici les options de cette commande :
Pour commencer nous allons utiliser l’option « follow »
docker-compose logs --follow
Cette option va nous attacher au conteneur et affichera les logs au fur et à mesure de leur apparition.
Par exemple, si l’on se connecte à la page web de ce serveur depuis un navigateur nous pourrons avoir les logs de cette connexion.
Par défaut, les logs s’affichent dans le terminal.
L’idée ici serait de pouvoir les rediriger dans un fichier pour pouvoir les conserver et les visionner ou traiter comme l’on veut.
Pour effectuer une redirection des logs, nous allons ajouter quelques lignes dans notre fichier « docker-compose.yml »
De la même manière que nous déclarons un volume, nous allons déclarer l’utilisation de la redirection des logs avec :
Attention : il existe plusieurs type de driver pour les logs. udp ET tcp sont compatibles, choisissez celui qui vous convient le mieux. Le port par défaut à utiliser pour gérer les logs est 514.
Comme à chaque fois, nous vérifions la configuration avec la commande « docker-compose config »
A nouveau il n’y a pas d’erreurs, nous pouvons donc instancier le conteneur
Puis nous refaisons la commande « docker-compose logs »
Cette fois-ci, nous avons un message d’alerte qui indique qu’aucun log n’est disponible via « syslog » pour ce service.
C’est normal, nous n’avons pas configuré « syslog »
Pour configurer syslog nous allons éditer le fichier « /etc/rsyslog.conf »
Ce que nous allons faire dans le fichier c’est simplement décommenter la partie en dessous de « provide UDP syslog reception »
Une fois les modifications enregistrées il faudra redémarrer le service « rsyslog »
Maintenant nous allons afficher les dernières lignes des logs de « syslog » avec la commande suivante :
tail -f /var/log/syslog
Retournons sur notre navigateur web pour à nouveau nous connecter sur le serveur web et vérifions ce qu’il se passe.
Dans un premier temps, nous pouvons voir que le serveur fonctionne et qu’il s’affiche correctement
Dans un second temps nous pouvons voir dans les dernières lignes de « syslog » que les logs de connexion que nous avions précédemment dans le terminal sont maintenant enregistrés.
Bien sûr ici il s’agit d’un exemple, il est possible de spécifier l’endroit exacte où l’on souhaite enregistrer ces logs.
Le but de cet l’exercice que nous allons faire dans cette partie de la documentation est de connecter notre service web sur le « logstash » qui lui-même va rediriger le tout vers « kibana »
ELK est un outil qui permet de récupérer les logs et de les afficher au format web via une interface assez « user friendly »
Pour commencer nous allons créer encore un répertoire pour y créer un fichier « docker-compose.yml »
Nous appellerons ce répertoire « elk »
Une fois le fichier « yml » créé nous allons l’éditer comme ceci :
Pour commencer nous allons instancier ces trois conteneurs :
Puis vérifier s’ils tournent correctement.
Un des conteneur est arrêté. C’est normal il y a une configuration à faire.
Pour cela il faudra se rendre dans le répertoire « conf » qui a été créé en même temps que le volume « conf » et y créer le fichier « gelf.conf ».
Ce fichier devra être configuré de cette manière :
On relance la commande « docker-compose up -d » SANS au préalable supprimer les volumes et les conteneurs que l’on vient de créer. Cela aura simplement pour effet de mettre à jour les conteneurs avec les nouvelles configurations. Dans notre cas seul le conteneur « logstash » sera mis à jour.
Vérifions à nouveau si les trois conteneurs sont up
Attention : Pour l’instant il ne faut pas les arrêter.
Maintenant que la partie « elk » est prête, nous allons revenir dans le répertoire « logs » et modifier notre fichier « docker-compose.yml » pour changer le driver que nous avions enregistré pour les logs ainsi que l’adresse pour enregistrer les logs.
Une fois les configurations faites, il ne nous reste plus qu’à nouveau instancier notre serveur web.
Normalement à ce stade nous devrions avoir 4 conteneurs actifs : les 3 conteneurs ELF plus le conteneur du serveur web.
Vérifions les logs avec la commande « docker-compose logs »
Les logs ne sont pas visibles. En effet un nouveau message d’erreur s’affiche nous indiquant que les logs sont disponibles via le driver « gelf ».
C’est une bonne nouvelle, cela indique bien que notre configuration est correcte et fonctionne.
Mans dans ce cas, comment accéder aux logs ?
C’est très simple, il suffit de se rendre directement sur l’interface graphique de « kibana » depuis le navigateur web pour pouvoir les afficher.
http://"ip_de_l’hôte":"5601"
Une fois sur cette page, nous allons sélectionner « @timestamp » dans la partie « Time-field name » puis cliquer sur « create ».
Ouvrons un nouvel onglet et connectons-nous sur notre serveur web. Si l’onglet est déjà ouvert il suffira de le rafraichir.
Revenons sur « Kibana » pour cliquer sur « discover » pour pouvoir consulter les logs
Si aucun log n’est visible dans la partie « discover », il sera possible de modifier le laps de temps durant lequel « Kibana » recherchera les logs.
Pour cela en haut à droite de l’onglet cliquez sur « last 15 minutes » et sélectionnez « today »
Rafraichir l’onglet du serveur web et cliquer de nouveau sur « discover » dans « Kibana ».
Les logs devraient être visibles.
Si l’on désire, il sera même possible de filtrer les logs que l’on recherche directement dans « Kibana ».
Pour cela il suffira de cliquer dans la barre de recherche et d’entrer le mot clé voulu (IP, nom d’une machine, type de log, etc.).
Par exemple, si nous recherchons « docker » nous verrons seulement les longs le concernant.