Table des matières

Docker compose

Après s'être familiarisé avec Docker, il faut passer à docker compose pour respecter un principe de ses architectures:

un conteneur = un service


ou presque… en effet on va trouver des conteneur apache/php ou nginx/php par exemple.

Développer

On va pouvoir mettre en œuvre un groupe de conteneurs pour avoir le serveur web(apache ou nginx) + php, le serveur de base de données (MariaDB, Posgres…), si besoin le phpmyadmin ou équivalent…
Il y a souvent quelques différences entre ce qui est défini en développement et en production… donc on va généralement avoir un docker-compose.yml différent pour les deux, même s'il y aura évidemment beaucoup de point commun.

Y a-t-il besoin de Dockerfile? … ça dépend si on a besoin de modifier la/les images(s) de base. Pour créer le conteneur PHP-nginx, on a en général besoin d'un Dockerfile pour ajouter nginx à l'image de base php et ajouter des modules… en revanche les conteneurs de bases de données en ont rarement besoin, le passage de variables d'environnement et de fichiers de configuration suffisent.

Le fichier docker-compose.yml va souvent contenir plusieurs configuration, notamment une pour le développement et une pour construire d'image de production. Celle de dév s'appelle souvent app. Pour les variables d'environnement, on aura aussi un .env et éventuellement un .env.local pour le dév. Cela peut donner, pour lancer l'instanciation du conteneur de dév :

docker compose --env-file .env.local up app -d
Ne pas confondre les variables d'environnement utiles au fichier docker-compose et celle passées à l'instance de conteneur créée, cf. https://stackoverflow.com/a/74544228/6614155. Si on ajoute dans le docker-compose.yml une ligne
env_file: .env.prod

les variables de ce fichier ne sont pas passée au docker-compose.yml mais directement au conteneur créé. cf. le projet banadora où j'ai commencé à l'appliquer et sur la VM en prod notamment pour les tests banadora et ceramo.

Réseau

Si on fait un

docker network ls

on visualise les différents réseaux, notamment bridge.
Un

docker inspect <id>

<id> est à remplacer par l'identifiant d'un réseau du type nomprojet_default, permet de voir le détail de ce réseau interne entre les conteneurs

En prod

Quelques précautions sont nécessaires lorsque nos conteneurs sont utilisés en production…

On évite au maximum d'arrêter des conteneurs de prod… donc si on a besoin de faire une modification, on modifie le fichier docker-compose.yml (attention les tabulations) puis on fait un

docker compose up -d

Il lit alors le fichier et met à jour les conteneurs. Exemple d'utilisation, ajouter un volume (dans ce cas, attention aux droits, pour un var/log, il faut bien le mettre en root et pas en www−data !)

Quand on ajoute un nouveau service, on peut commencer par n'exécuter que ce service avec :

docker compose up monService

qu'on peut quitter avec Ctrl+Z en laissant en tâche de fond (cf. https://gitlab.huma-num.fr/bdavid/admin-serveur/-/issues/6)

Restart

Surprise, votre serveur web est arrêté… suite au redémarrage du host après des mises à jour par exemple.
Il faut bien que chaque conteneur (service) comporte la ligne:

restart: always

Registres

Il est souvent pratique de sauvegarder nos images dans un “registre” (registry), notamment gitlab… s'il est instancié. Ainsi l'instance gitlab.huma-num.fr n'en dispose pas alors que gitlab.in2p3.fr en dispose.
Il faut créer un projet dans le gitlab et définir un token avec lecture/écriture pour pouvoir pousser et tirer les images. Pour ce token, on va dans le menu Settings puis Access Token. On crée un token en saisissant un nom, puis en cochant read_registry et write_registry et validant le bouton Create project access token, bien récupérer le token (à mémoriser dans un séquestre !), allez ensuite dans le menu members et mémoriser le nom associé qui se trouve sous le nom donnée au token, après le caractère @
Voir aussi : registry-gitlab

Ensuite pour “pousser” l'image dans le registre, il faut sur le serveur ou la machine de développement, tout d'abord se connecter avec notre token :

docker login <adresse-du-serveur>/<nom-utilisateur>/<nom-du-projet>/<nom-du-registre>

qui va demander le nom et le mot de passe du token, mémoriser précédemment dans notre séquestre,
puis, on “pousse” avec

docker push <adresse-du-serveur>/<nom-utilisateur>/<nom-du-projet>/<nom-du-registre>:<tag>

puis, sur le serveur, il faut récupérer l'image à jour avec :

docker pull <adresse-du-serveur>/<nom-utilisateur>/<nom-du-projet>/<nom-du-registre>:<tag>

puis mettre à jour l'instance en production :

docker compose up -d

qui ne met à jour (Recreating) que la ou les instance(s) dont l'image a évoluée.

Logs

Il est souvent utile de visualiser les logs d'un conteneur.
On peut simplement faire :

docker logs nom-du-conteneur

et si on veut comme pour un tail -f /var/log…

docker logs -f --tail 10 nom-du-conteneur

ou 10 est à priori le nombre de lignes