Avec Docker, la création de conteneurs peut s'avérer assez longue et perturbante. Ainsi, la méthode des compositions docker avec docker-compose
permet de simplifier fortement la conception d'installations Docker complexes. Le principe est basé sur un fichier docker-compose.yml
utilisant le format YAML/YML
dont la comprehension est assez facile à saisir.
Le langage YAML/YML est sensible à la casse et aux espaces/tabulations. En cas d'erreur de tab/space, la composition est tout simplement ignorée et une erreur sortira. Rien n'est créé si une erreur est générée.
{.is-warning}
La Composition - Les Bases
Concept de Services
Lors de la création d'un Compose, on parlera de services et on nommera ces derniers. Par défaut, Docker choisira les noms des conteneurs mais nous pouvons les spécifier si besoin.
Exemple basique
services:
nom_service1:
image: fournisseur/image:versiontag
container_name: mon_conteneur1
ports:
- 80:80
- 443:443
volumes:
- /données:/data
- /ssl:/etc/ssl
entrypoint: /init
Ce Compose basique permet de voir les paramêtres de bases d'un compose. C'est à dire :
- L'entête, marqué
services:
- Le nom du service
- l'image avec son fournisseur et sa version/edition :
fournisseur/image:versiontag
Le taglatest
est courant : En effet, cela permet d'avoir toujours la dernière version de l'image. Attention cependant : Si vous souhaitez figer la version entre lesup
, il faudra utiliser un tag fixe. Voir la page Docker Hub de l'image dans l'onglet "Tags".
- le nom de conteneur (facultatif)
- les ports exposé a Internet/Intranet/Réseau Local dans le sens
externe:interne
- les volumes, ici ce sont des binds.
- Le point d'entrée (démarreur alternatif) défini pour ce service. Ce paramêtre est spécifique aux applications web, mais vous pourriez le recontrer beaucoup de fois !
Depuis la version 3 du programme Docker-Compose, l'indication de version avantservice:
n'est plus obligatoire. Elle peut être encore présente dans des composes sur les gits des applications. Lorsqueversion:
n'est pas précisé, alors la dernière version du composite est utilisé, la plupart du temps, cela n'a aucun effet si vous n'utiliser pas de fonction très avancée.
{.is-info}
Exemple Basique MultiServices sans Dépendances
Ici, nous vous montrons un exemple de compose méttant en scéne plusieurs services.
services:
nom_service1:
image: fournisseur/image:versiontag
container_name: mon_conteneur1
ports:
- 80:80
- 443:443
volumes:
- /données:/data
- /ssl:/etc/ssl
entrypoint: /init
nom_service2:
image: fournisseur2/image2:versiontag
container_name: mon_conteneur2
ports:
- 336:3336
- 8800:8080
volumes:
- /données/sql:/var/lib/mysql
Dans cet exemple, nous avons :
- Le Service 1 avec 2 ports, 2 volumes et un point d'entrée
- Le Service 2 avec 2 ports, 1 volume et pas de point d'entrée.
Ici, Le conteneur 1 et le conteneur 2 ne pourront pas communiquer facilement. Car aucune dépendances n'a été définie. Ceci est résolu ci-dessous.
Exemple Basique MultiServices avec Dépendances
Contrairement au précedent exemple, nous allons relier les services en définissant une dépendance.
services:
nom_service1:
image: fournisseur/image:versiontag
container_name: mon_conteneur1
ports:
- 80:80
- 443:443
volumes:
- /données:/data
- /ssl:/etc/ssl
depends_on:
- nom_service2
entrypoint: /init
nom_service2:
image: fournisseur2/image2:versiontag
container_name: mon_conteneur2
ports:
- 336:3336
- 8800:8080
volumes:
- /données/sql:/var/lib/mysql
Ici, nous ajoutons depends_on:
et listons les services dont dépend ce service. Une dépendance est a sens unique logique. Mais les deux conteneurs pourront communiquer l'un vers l'autre et l'autre vers l'un. A ne pas confondre avec links:
!
Une dépendance permet aux deux conteneurs de connaître, par DNS interne, le nom et l'IP de l'autre conteneur. Ceci est souvent utilisé pour des bases SQL externes ou des services liés. Ce qui permet aussi de les relier avec une sécurité avancée niveau ports, car le port SQL ne doit jamais être exposé au Web ou a l'Intranet/Réseau Local
{.is-info}
Fonctionnement Général
Les ports
Dans les compositions, vous définissez les ports exposé a Internet ou au Réseau par la partie suivante :
ports:
- 80:8080
- 443:4443
Le fonctionnement est défini tel que : [port externe]:[port interne]
.
Il est aussi possible de définir le mode de communication des ports. Par défaut, c'est l'accés par TCP qui est défini.
ports:
- 80:8080/tcp
- 443:4443/tcp
Définir un mode permet d'interdir l'usage de l'autre mode. Les modes disponibles sont :
- TCP (Mode Web Général)
- UDP (Mode Peer-2-Peer)
- Internal (Mode Hôte)
Vous pouvez définir les deux modes comme actifs en définissant le même port deux fois pour chacun des modes :
ports:
- 80:8080/tcp
- 80:8080/udp
- 443:4443/tcp
- 443:4443/udp
Ici, les ports seront accessible par TCP et UDP.
Attention, l'activation d'UDP sur des services qui ne le nécessite pas du tout est un potentiel risque de sécurité important. L'application et le conteneur n'ayant pas de prévention UDP, il est possible de pirater ce conteneur en utilisant l'UDP. Ainsi, la prudence est de rigueur ! Par défaut, on active jamais UDP.
{.is-warning}
Port Overlap, c'est quoi ?
Un Port Overlap est un phoénomen qui se produit lorsque un conteneur, un compose ou un stack demande l'accés a un port déjà utilisé par un autre service sur Docker ou sur l'Hôte. Sur l'hôte, chaque port ne peut être utilisé par Docker qu'une seule fois. Ainsi, il faudra s'organiser afin de permettre l'usage d'un autre port. Exemple :
- Nous installons Nginx Proxy Manager sur nos ports
80
,443
et81
. - Nous voulons installer un serveur Apache HTTPD et nous voulons le mettre sur le port
80
.
Si l'OS a un serveur Apache HTTPD installé en dur (sans Docker), et que Docker met en service un Nginx PM sur le port80
, c'est Nginx PM qui sera prioritaire. Tout les ports ne font pas d'Overlap pour des services sur l'OS. Mais ce sont toujours ceux de Docker qui seront délivrés en premier.
{.is-info}
Ici, il faudra trouver un port alternatif pour HTTPD. Dans cette situations, deux possibilités :
- Respecter les standards mais aussi ses limites, et utiliser le port
8080
, deuxiéme port HTTP standard au lieu de80
. - Ne pas respecter les standards, et être libre comme GNU, et utiliser le port
82
qui se trouve juste aprés le port81
de Nginx Proxy Manager. Cette méthode est recommandé et permettra plus tard plus de possibilitées !
Pour l'organisation, il sera possible de s'organiser tel que :
- Application 1 - Port
200
- Sous Application 1 de l'Application 1 - Port
201
- Sous Application Test 1 de l'Application 1 - Port
210
Ainsi, nous maintenons une logique de ports et n'utilisons pas les standards.
Le seul cas ou l'usage des standards est requis, c'est quand l'application utilise de manière directe son port pour communiquer et pas SSL ou les requêtes HTTP/S. Ce qui reste extremement rare et largement dépassé. Mais techniquement, si elle le fesait, le port utilisé à l'exterieur sera celui choisi par vous et pas son port interne.
{.is-warning}
Exemple de déploiement #1 : Trilium Notes
Trilium Note est une application de prise de notes personnelle et privée. Docker Compose peut être utilisé pour déployer Trilium Note de manière simple et efficace. Voici les étapes à suivre pour déployer une instance de cette application :
Créez un fichier docker-compose.yml ou compose.yml dans un dossier de votre choix.
Ajoutez le contenu suivant au fichier docker-compose.yml :
version: '3'
services:
trilium:
image: zadam/trilium
volumes:
- ./trilium-data:/root/.local/share/trilium
ports:
- "8080:8080"
Créez un dossier trilium-data dans le même dossier que le fichier docker-compose.yml. Ce dossier sera utilisé pour stocker les données de Trilium Note.
Ouvrez un terminal et accédez au dossier contenant le fichier docker-compose.yml.
Exécutez la commande suivante pour démarrer le conteneur Trilium Note
Commande : docker-compose up -d
Vous pouvez maintenant accéder à Trilium Note en ouvrant un navigateur et en accédant à l'URL http://localhost:8080.
Pour arrêter le conteneur, exécutez la commande suivante :docker-compose down
Notez que cette configuration utilise l'image Docker officielle de Trilium Note, qui est maintenue par la communauté et peut être mise à jour régulièrement. En outre, les données de Trilium Note sont stockées dans le dossier trilium-data, ce qui permet de conserver les données même si le conteneur est arrêté ou supprimé, il s'agit de la persistence des données.