Le fichier de Docker Compose

La base du fichier Docker Compose

Le fichier de Docker Compose (généralement, et pour la suite de ce cours, nommé docker-compose.yml) a systématiquement 2 clefs à sa racine : version et services. En effet le format du fichier Docker Compose a changé au cours du temps (nous en sommes à la version 3) et il est donc utile de préciser le format du fichier courant. Le reste du fichier sera consacré à la description des différents services (entendre ici conteneurs) que nous voulons gérer.

En prenant pour exemple le fichier précédent, son squelette est :

1
version: '3'
2
services:
3
  traefik:
4
    [...]
5
6
  registry:
7
    [...]

Ce fichier utilise le format Docker Compose en version 3 et décrit 2 services :

  • traefik

  • registry

La configuration de chacun des services sera ensuite décrites à l'intérieur de chacun des blocs.

Correspondances entre la CLI Docker et le format Docker Compose

Pour chaque service, différentes options peuvent être configurées dans le fichier Docker Compose. La liste est disponible dans la (très complète) documentation de Docker Compose que nous vous incitons à garder dans un coin. Nous n'allons pas entrer dans le détail des options, mais simplement décrire celles qui nous permettant de remplacer les options de la CLI que nous avons vu dans les parties précédentes.

  • container_name permet de nommer le conteneur (équivalent à --name)

  • environment est la liste des variables d'environnement à passer au conteneur (équivalent à --environment)

  • image est le nom de l'image Docker à utiliser

  • ports est la liste des ports que l'on souhaite connecter entre l'hôte et le conteneur

  • volumes est la liste des volumes que l'on souhaite monter dans le conteneur. Cette notion n'a pas encore été vue, mais sachez que les bind mounts sont une forme de volume et trouvent leur place dans cette liste.

Avec ces informations, on peut désormais interpréter les informations des services du fichier docker-compose.yml précédent. Par exemple le service traefik était configuré ainsi :

1
  traefik:
2
    image: traefik:latest
3
    container_name: traefik
4
    ports:
5
      - "80:80"
6
      - "443:443"
7
    volumes:
8
      - /var/run/docker.sock:/var/run/docker.sock
9
      - /DOCKER/volumes/traefik/traefik.toml:/traefik.toml
10
      - /DOCKER/volumes/traefik/certs:/certs

Ici le service traefik va créer un conteneur nommé traefik à partir de l'image traefik:latest. Le port 80 du conteneur va être exposé sur le port 80 de l'hôte, de même pour le port 443. De plus 3 bind mounts permettent de monter, dans le conteneur, les fichiers /var/run/docker.sock et /DOCKER/volumes/traefik/traefik.toml ainsi que le dossier /DOCKER/volumes/traefik/certs. On constate que la syntaxe de chaque option respecte celle de l'outil en ligne de commande de Docker.

De la même manière, on peut analyser le service registry :

1
  registry:
2
    image: registry:2
3
    container_name: registry
4
    environment:
5
      REGISTRY_AUTH: htpasswd
6
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
7
    volumes:
8
      - /DOCKER/volumes/registry/data:/var/lib/registry
9
      - /DOCKER/volumes/registry/auth:/auth
10
    labels:
11
      - "traefik.frontend.rule=Host:registry.picasoft.net"
12
      - "traefik.port=5000"
13
      - "traefik.enable=true"

Un conteneur nommé registry est créé à partir de l'image registry:2. On monte 2 dossiers de l'hôte en bind mounts et on passe 2 variables d'environnement au conteneur : REGISTRY_AUTH (valeur htpasswd) et REGISTRY_AUTH_HTPASSWD_PATH (valeur /aut/htpasswd). On assigne aussi 3 labels au conteneur. Les labels sont une notion que nous n'avons pas abordé, il faut simplement savoir qu'il est possible de mettre des labels (un couple clef/valeur) aux conteneurs (avec le mot clef labels).

Gestion des dépendances

Un intérêt de Docker Compose est aussi de gérer les dépendances entre conteneur. Dans l'exemple de fichier qui nous prenons, le service registry nécessite que le service traefik soit démarré pour fonctionner correctement. Pour cela on peut utiliser la clef depends_on qui prend en paramètre la liste des services dont dépend un conteneur. Par exemple, dans le cas de notre service registry, on pourrait ajouter :

1
  registry:
2
    depends_on:
3
      - traefik
4
    [...]

Gestion des réseaux

Docker Compose permet aussi de connecter différents conteneurs à un même réseau.

Reprenons l'exemple que nous avons vu plus tôt dans ce cours. Nous avions créé 2 conteneurs avec les commandes suivantes :

1
docker run -it --name container1 --net myfirstnet debian bash
2
docker run -it --name container2 --net myfirstnet debian bash

Avec Docker Compose, on peut attacher les conteneurs à un réseau à l'aide de la clef networks dans un service. De plus il faut rajouter une autre clef networks à la racine du fichier docker-compose.yml pour décrire les différents réseaux. En pratique :

1
version: '3'
2
services:
3
  firstcontainer:
4
    image: debian
5
    container_name: container1
6
    networks:
7
      - myfirstnet
8
  secondcontainer:
9
    image: debian
10
    container_name: container2
11
    networks:
12
      - myfirstnet
13
14
networks:
15
  myfirstnet:
16
    external: true

On constate que, à la fin du fichier, il est nécessaire de définir tout les réseaux qui sont utilisés dans le fichier. Ici l'ajout de external : true permet d'indiquer à Docker Compose que le réseau Docker nommé myfirstnet existe déjà sur la machine (nous l'avions créé précédemment). Si ce n'est pas spécifié, Docker Compose va créer directement un réseau mais avec un nom qui n'est pas forcément exactement celui que l'on souhaite (un mélange entre le nom du dossier du fichier et le nom du réseau).

C'est donc une bonne pratique de systématiquement créer ses réseaux manuellement (avec docker network create) et d'utiliser la directive external.