Module 05 · Docker DevOps · Chapitre 7

7. Docker Compose

Décrire plusieurs services Docker comme une application cohérente : configuration, communication, données et cycle de vie.

7.1 Pourquoi Docker Compose ?

Un conteneur répond à un besoin précis : exécuter un processus dans un environnement isolé. Une application complète comprend souvent plusieurs composants : un serveur web, une API, une base de données, un cache ou un service de traitement.

Avec Docker seul, chaque conteneur peut être géré séparément. Mais il faut alors conserver la cohérence des paramètres : réseaux, volumes, ports, variables et ordre de démarrage.

Service web
↔
API
↔
Base de données

Docker Compose permet de décrire cet ensemble dans un fichier de configuration, puis de gérer les services comme un projet. Compose ne remplace pas Docker Engine : il s'appuie sur lui pour créer et gérer les objets Docker.

À retenir :

Docker exécute les conteneurs ; Compose décrit et coordonne les ressources nécessaires à une application composée de plusieurs services.

7.2 Le modèle déclaratif et le projet Compose

Compose adopte une approche déclarative : on décrit la configuration attendue de l'application plutôt que d'énumérer toutes les étapes de création de chaque conteneur.

Le fichier Compose est une déclaration de configuration, pas une photographie de l'état réel. Compose interprète cette déclaration et demande à Docker Engine les opérations nécessaires lors des commandes de gestion.

NotionSignificationPour approfondir
ProjetEnsemble logique de services et de ressources gérés ensemble, identifié par un nom de projet.
ServiceDéfinition d'un composant applicatif et de sa configuration ; il peut correspondre à un ou plusieurs conteneurs.
ConteneurInstance concrète exécutée à partir de la définition d'un service.
RessourcesRéseaux et volumes éventuellement créés ou réutilisés par le projet.

Le nom du projet sert notamment à regrouper et identifier les ressources. Plusieurs projets Compose peuvent cohabiter sur une même machine, avec des noms et des ressources distincts.

7.3 La structure d’un fichier compose.yaml

Le fichier usuel est compose.yaml (ou compose.yml). Il utilise le format YAML, où l'indentation structure les relations entre les éléments.

Et si nous reprenions notre exemple d’architecture comme fil rouge pour découvrir le fichier compose.yaml ?

Deux réseaux distincts : web NGINX dans frontend, db MariaDB dans backend, app WordPress à cheval sur les deux réseaux.

Un fichier Compose regroupe les définitions des services et les ressources partagées du projet. Voici une vue simplifiée de sa structure :

services:
  nom_de_mon_service:
    image: mon_image:semver
    ports: (...)
    environment: (...)
    secrets: (...)
    volumes: (...)
    networks: (...)
    healthcheck: (...)
    depends_on: (...)

networks: (...)

volumes: (...)

secrets: (...)

Explication du fichier Compose :

Élément à découvrirComment le lire ?Pour comprendre la suite
servicesAu niveau racine, cette clé regroupe les composants de l’application. nom_de_mon_service est un nom de service choisi dans le projet.7.4 — Services, images et construction
image / buildIndiquent quelle image utiliser ou comment la construire. Ici, le service référence une image par son nom et son tag.7.4 — Services, images et construction
ports / networksDécrivent l’accès depuis l’hôte et les réseaux auxquels les services sont connectés. La clé networks au niveau racine déclare les réseaux du projet.7.5 — Réseaux et communication
volumesSous un service, décrit les montages. Au niveau racine, déclare les volumes nommés du projet.7.6 — Volumes et persistance
environment / secretsFournissent la configuration et l’accès aux données sensibles. Les secrets sont déclarés au niveau racine, puis attribués aux services concernés.7.7 — Configuration, variables et secrets
depends_on / healthcheckDécrivent les dépendances de démarrage et les contrôles de santé.7.8 — Dépendances et disponibilité
À retenir :

commencer par identifier les services, puis lire leur configuration. Les ressources déclarées au niveau racine sont référencées par les services qui les utilisent. Toutes les clés présentées ne sont pas obligatoires pour chaque service.

Un exemple complet sera présenté en 7.11 — Scénario : NGINX, WordPress et MariaDB, après l’explication de ces notions.

7.4 Services, images et construction

Un service Compose définit la façon dont un composant doit être exécuté. Il peut préciser l'image, la commande, les variables, les ports, les montages et les réseaux.

Deux modes d'obtention de l'image sont fréquents :

  1. image: nginx:stable : Référence une image par son nom et son tag.
    services:
      web:
        image: nginx:stable
  2. build: ./api : Décrit un contexte de construction local, généralement associé à un Dockerfile.
    services:
      api:
        build: ./api

    Le chemin ./api désigne le contexte de construction, relatif au fichier Compose. Par défaut, Compose y cherche un fichier nommé Dockerfile.

    Exemple minimal de ./api/Dockerfile :

    FROM nginx:stable-alpine
    COPY index.html /usr/share/nginx/html/index.html

    FROM choisit l’image de base. COPY copie le fichier ./api/index.html dans l’image construite, à l’emplacement servi par NGINX.

    Ainsi, build: ./api fournit le dossier de construction ; ./api/Dockerfile décrit comment construire l’image du service api. Le nom api est ici un nom de service : cet exemple minimal sert une page HTML.

Point de vigilance : un tag d'image n'est pas nécessairement immuable. Pour maîtriser précisément ce qui est déployé, le choix des versions d'images reste important, comme vu au chapitre 3 — Images Docker.

7.5 Réseaux et communication entre services

Compose crée généralement un réseau par défaut propre au projet.

Les services connectés à un même réseau peuvent communiquer entre eux en utilisant leur nom de service comme nom DNS, sans dépendre d'une adresse IP de conteneur susceptible de changer.

1. Déclarer les réseaux et y connecter les services

Dans notre architecture, nous choisissons deux réseaux explicites. Voici uniquement les éléments concernés du fichier Compose :

services:
  web:
    networks:
      - frontend

  app:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend

networks:
  frontend:
  backend:

La clé networks au niveau racine déclare les deux réseaux du projet. Sous chaque service, networks indique à quels réseaux ses conteneurs sont connectés.

  • web peut joindre app sur frontend. NGINX utilise l’adresse app:80 dans sa configuration.
  • app peut joindre db sur backend. WordPress utilise l’adresse db:3306 pour sa connexion à MariaDB.
  • web est uniquement sur frontend et db uniquement sur backend : ils ne partagent aucun réseau.

Connecter app aux deux réseaux ne crée pas automatiquement une liaison réseau directe entre web et db. Voir le chapitre 5, section 5.2.4 — Règles de communication et sécurisation.

2. Publier un port sur l’hôte

services:
  web:
    ports:
      - "8080:80"

La clé ports est placée sous le service web. La valeur "8080:80" associe le port 8080 de l’hôte au port 80 du conteneur NGINX.

Grâce à cette publication, le client sur l’hôte peut atteindre NGINX à l’adresse localhost:8080. Sans elle, une connexion à localhost:8080 ne serait pas transmise au port 80 du conteneur web.

Points intéressants :

  1. Les échanges entre web et app, puis entre app et db, se font directement sur les réseaux Docker qu’ils partagent, via app:80 et db:3306.
  2. Publier les ports d’app et de db sur l’hôte est donc inutile pour ces échanges.
  3. Dans notre architecture, il est recommandé de ne pas les publier afin de limiter l’exposition de l’application et de la base de données.
  4. Seul web possède une déclaration ports, car c’est le seul service qui doit être joignable depuis l’hôte.

Pour approfondir la différence entre port interne et port publié, voir le chapitre 5, section 5.3 — Ports et exposition des services.

À retenir :

networks définit les réseaux partagés par les services ; ports rend un port de conteneur accessible via un port de l’hôte.

7.6 Volumes et persistance des données

Les données écrites dans la couche modifiable d’un conteneur sont perdues lorsque ce conteneur est supprimé. Notre architecture utilise donc des montages pour fournir la configuration et conserver les données.

1. Fournir un fichier de l’hôte : le bind mount

services:
  web:
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
  1. ./nginx/default.conf est le fichier source sur l’hôte, dont le chemin est relatif au fichier Compose.
  2. /etc/nginx/conf.d/default.conf est son emplacement dans le conteneur.
  3. :ro rend ce montage accessible en lecture seule dans le conteneur.
Modes d’accès au montage

Il y a deux possibilités :

  • :ro → Lecture seule : le conteneur peut lire les fichiers, mais ne peut pas les modifier via ce montage.
  • :rw → Lecture et écriture : le montage permet de lire et de modifier les fichiers. C’est le mode par défaut si aucune option n’est précisée.

Ces modes ne modifient pas les permissions du fichier sur l’hôte !

NGINX lit ainsi la configuration fournie par l’hôte, sans reconstruire son image. Ce montage fournit un fichier ; il ne décrit pas lui-même le comportement du serveur.

2. Conserver les données : les volumes nommés

services:
  app:
    volumes:
      - wordpress_data:/var/www/html

  db:
    volumes:
      - db_data:/var/lib/mysql

volumes:
  wordpress_data:
  db_data:
  1. Au niveau racine, volumes déclare les volumes nommés du projet.
  2. Sous app, wordpress_data est monté dans /var/www/html pour conserver les fichiers WordPress.
  3. Sous db, db_data est monté dans /var/lib/mysql pour conserver les données MariaDB.
StockageCaractéristique
Volume nomméGéré par Docker ; adapté à la conservation des données applicatives.
Bind mountAssocie un chemin de l’hôte à un chemin du conteneur ; utile notamment pour fournir une configuration.
À retenir :

un volume nommé peut survivre à la suppression du conteneur, mais il peut lui-même être supprimé. La persistance ne remplace pas une sauvegarde.

Pour aller plus loin : Compose peut référencer un volume déclaré comme external, déjà existant et dont le cycle de vie est géré en dehors du projet. Ce n’est pas le cas des deux volumes de notre scénario.

7.7 Configuration, variables et secrets

La configuration peut être fournie au démarrage, sans être intégrée à l’image. Notre scénario distingue les paramètres ordinaires et les mots de passe.

MécanismeFonction
Interpolation ${VARIABLE}Compose remplace une valeur du YAML à partir de son environnement ou de sources telles qu’un fichier .env.
environment / env_fileFournit des variables au processus exécuté dans le conteneur.
secretsRend des données sensibles accessibles aux services autorisés, sous forme de fichiers dans notre scénario.

1. Fournir les paramètres avec environment

services:
  app:
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password

  db:
    environment:
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD_FILE: /run/secrets/db_password
      MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root_password

Ces noms de variables sont reconnus par les images WordPress et MariaDB : Compose les transmet, et les images définissent leur signification.

VariableRôle dans notre scénario
WORDPRESS_DB_HOSTAdresse de MariaDB : nom de service db et port interne 3306.
WORDPRESS_DB_NAME / WORDPRESS_DB_USERBase et compte utilisés par WordPress.
MARIADB_DATABASE / MARIADB_USERBase et compte applicatif à créer lors de l’initialisation de MariaDB.
WORDPRESS_DB_PASSWORD_FILE / MARIADB_PASSWORD_FILEChemin du fichier contenant le même mot de passe pour le compte applicatif, lu par chaque image.
MARIADB_ROOT_PASSWORD_FILEChemin du fichier contenant le mot de passe du compte root de MariaDB.
Initialisation de MariaDB

Les variables d’initialisation de MariaDB s’appliquent à une base nouvellement initialisée. Modifier ces valeurs dans Compose ne modifie pas automatiquement les comptes d’une base déjà conservée dans db_data.

2. Déclarer les secrets et les attribuer aux services

services:
  app:
    secrets:
      - db_password

  db:
    secrets:
      - db_password
      - db_root_password

secrets:
  db_password:
    file: ./secrets/db_password.txt
  db_root_password:
    file: ./secrets/db_root_password.txt
  1. Au niveau racine, secrets déclare les secrets et leurs fichiers sources sur l’hôte.
  2. Sous chaque service, secrets accorde l’accès aux secrets nécessaires : app reçoit le mot de passe applicatif ; db reçoit les deux. web ne reçoit aucun secret.
  3. Compose les rend accessibles dans les conteneurs sous /run/secrets/db_password et, pour MariaDB uniquement, /run/secrets/db_root_password.
  4. Les variables _FILE de l’extrait précédent indiquent aux images où lire ces mots de passe. Ce suffixe est une convention prise en charge par ces images, pas un mécanisme universel de Compose.
Sécurité : protéger les fichiers sources sur l’hôte et les exclure du dépôt Git. Avec Compose local, cette déclaration ne chiffre pas les fichiers sources. Les mots de passe ne doivent pas être intégrés à l’image ni au fichier Compose versionné.

3. Utiliser l’interpolation

Exemple d’interpolation d’une valeur non sensible

À côté de compose.yaml, le fichier .env peut contenir :

DB_NAME=wordpress

Compose peut utiliser cette valeur dans le fichier YAML :

services:
  app:
    environment:
      WORDPRESS_DB_NAME: ${DB_NAME}

  db:
    environment:
      MARIADB_DATABASE: ${DB_NAME}
  1. Compose lit DB_NAME depuis son environnement ou le fichier .env ; une valeur dans son environnement est prioritaire.
  2. Il remplace ${DB_NAME} par wordpress avant de créer les conteneurs : c’est l’interpolation.
  3. La clé environment transmet ensuite WORDPRESS_DB_NAME=wordpress à WordPress et MARIADB_DATABASE=wordpress à MariaDB. Le nom DB_NAME n’est pas automatiquement transmis aux conteneurs.

Pour l’interpolation, seules les variables référencées dans compose.yaml fournissent les valeurs à remplacer. Les autres variables présentes dans .env ne sont pas automatiquement injectées dans les conteneurs.

Interpolation et environnement du conteneur

Une variable utilisée dans compose.yaml peut aussi servir à définir un port ou une image. Sa valeur n’est transmise au conteneur comme variable d’environnement que si elle est déclarée pour l’environnement de ce service.

La forme ${DB_NAME:-wordpress} fournit une valeur par défaut si la variable est absente ou vide.
La forme ${DB_NAME:?Définir DB_NAME} demande une valeur non vide et signale une erreur sinon.

Lire ${DB_NAME:?Définir DB_NAME}
  • :? est la syntaxe : elle exige une variable définie et non vide.
  • Définir DB_NAME est le texte affiché si cette condition n’est pas remplie. Ce message est libre et peut être écrit en français.

Choisir un autre fichier pour l’interpolation

Par défaut, Compose utilise le fichier .env.
Pour utiliser, par exemple, .env.production, on le sélectionne avec l’option --env-file :

docker compose --env-file ./.env.production up

Le comportement de l’interpolation reste identique.

4. Fournir les variables avec env_file

Déclarer env_file sous un service permet de fournir au conteneur les variables contenues dans un fichier :

services:
  app:
    env_file:
      - ./app.env

Le fichier app.env contient des lignes de la forme NOM=valeur, par exemple WORDPRESS_DB_NAME=wordpress.
Compose transmet TOUTES ces variables au conteneur app.

En résumé :
  • Le fichier .env utilisé pour l’interpolation n’injecte pas automatiquement ses variables dans les conteneurs. Compose utilise leurs valeurs pour remplacer les expressions ${VARIABLE} dans compose.yaml ; leur utilisation sous environment permet ensuite de les transmettre au conteneur.
  • Déclarer env_file sous un service transmet toutes les variables du fichier ciblé au conteneur de ce service, sauf celles remplacées par environment. Les noms doivent correspondre à ceux attendus par l’application : pour WordPress, le fichier doit par exemple contenir WORDPRESS_DB_NAME=wordpress, et pas simplement DB_NAME=wordpress.

L’interpolation et env_file sont des possibilités complémentaires ; notre YAML final utilise directement environment et secrets.

7.8 Dépendances et disponibilité des services

Démarré ne signifie pas prêt : une base de données peut avoir lancé son processus sans encore accepter les connexions applicatives.

1. Exprimer les dépendances de démarrage

services:
  web:
    depends_on:
      - app

  app:
    depends_on:
      db:
        condition: service_healthy
  1. Pour web, la forme simple demande que app soit démarré avant lui. Elle ne vérifie pas que WordPress est prêt à répondre.
  2. Pour app, la forme détaillée avec condition: service_healthy attend que le contrôle de santé de db indique un état sain avant son démarrage.

2. Définir le contrôle de santé de MariaDB

services:
  db:
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10
ÉlémentLecture
testCommande du contrôle, exécutée dans le conteneur. Le script healthcheck.sh est fourni par l’image MariaDB.
CMDExécute directement la commande et ses arguments, sans passer par un shell.
--connect / --innodb_initializedVérifient la possibilité de connexion et l’initialisation d’InnoDB, le moteur de stockage.
interval: 10sIntervalle entre les contrôles.
timeout: 5sDurée maximale d’un contrôle avant qu’il soit considéré en échec.
retries: 10Nombre d’échecs consécutifs avant que le conteneur soit déclaré non sain.
À retenir
Conteneur créé
→
Processus démarré
→
Service prêt / sain

Ces étapes ne sont pas équivalentes.

  1. Le contrôle de santé évalue les critères définis → il ne garantit pas que tout le site fonctionne.
  2. Un état non sain ne provoque pas, à lui seul, un redémarrage automatique par Compose.

Ces dépendances organisent le démarrage. Après celui-ci, une application robuste doit aussi gérer les indisponibilités et les reconnexions : depends_on ne remplace pas ce comportement applicatif.

7.9 Cycle de vie et portée de Compose

Une fois les services et leurs ressources décrits, Compose permet de gérer leur cycle de vie comme un projet. Dans notre scénario, cela concerne web, app, db, leurs réseaux et leurs volumes.

Compose est couramment utilisé au moyen de la commande docker compose (plugin Compose moderne). Il interagit avec Docker Engine et gère les ressources du projet.

Commande (repère théorique)Signification
docker compose upCrée et démarre les services du projet, en réconciliant une partie de leur configuration.
docker compose psPrésente l'état des conteneurs du projet.
docker compose logsConsulte les journaux des services.
docker compose stopArrête les conteneurs sans supprimer les ressources du projet.
docker compose downArrête et supprime les conteneurs et réseaux du projet créés par Compose ; les volumes nommés ne sont pas supprimés par défaut.

La forme historique docker-compose (avec trait d'union) se rencontre encore dans d'anciens supports ; la syntaxe moderne est docker compose.

La déclaration Compose décrit l'application.
Docker Engine reste chargé de l'exécution effective des conteneurs sur l'hôte ciblé.

7.10 Compose et Kubernetes : deux niveaux différents

Notre fichier décrit une application cohérente sur un hôte Docker. Cela ne lui apporte pas automatiquement les capacités d’un orchestrateur de cluster.

Compose et Kubernetes utilisent tous deux des descriptions déclaratives, mais ils ne répondent pas au même besoin opérationnel.

Docker ComposeKubernetes
Décrit et gère une application composée de services, généralement sur un moteur Docker.Orchestre des charges de travail sur un ensemble de nœuds.
Adapté notamment aux environnements de développement, de test et à des déploiements simples.Conçu pour la planification, le maintien de l'état souhaité et la gestion d'applications distribuées.
Peut démarrer plusieurs instances d'un service selon les contraintes de l'hôte.Dispose de contrôleurs de réconciliation et de mécanismes d'ordonnancement sur les nœuds.

Compose ne constitue pas, à lui seul, un orchestrateur de cluster comparable à Kubernetes. Le fait de décrire plusieurs conteneurs dans un fichier YAML ne suffit pas à fournir les mêmes mécanismes de disponibilité, de placement et de reprise.

À retenir :

Compose structure une application multi-services ; Kubernetes orchestre des charges de travail à l'échelle d'un cluster.

7.11 Scénario : NGINX, WordPress et MariaDB

1. Architecture

Reprenons notre architecture du chapitre 5, section 5.2.4 — Règles de communication et sécurisation : un serveur web sur le réseau frontend, une application connectée aux deux réseaux, et une base de données accessible uniquement sur backend.

web dans frontend, db dans backend et app au premier plan à cheval sur les deux réseaux distincts

Lecture de l’architecture :

  • Le client atteint web via localhost:8080 sur l’hôte.
  • NGINX transmet à app:80 sur frontend.
  • WordPress contacte MariaDB via db:3306 sur backend.
  • Le conteneur db n’est ni connecté à frontend, ni publié sur l’hôte.

2. Le fichier de configuration

Afin de déclarer cette architecture avec Docker Compose, nous pourrions utiliser le fichier compose.yaml suivant :

services:
  web:
    image: nginx:stable-alpine
    ports:
      - "8080:80"
    volumes:
      # Bind mount : fichier de configuration NGINX fourni par l'hôte
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    networks:
      - frontend
    depends_on:
      - app

  app:
    image: wordpress:php8.3-apache
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
    volumes:
      # Volume nommé : conservation des fichiers WordPress
      - wordpress_data:/var/www/html
    networks:
      - frontend
      - backend
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mariadb:11.4
    environment:
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wordpress
      MARIADB_PASSWORD_FILE: /run/secrets/db_password
      MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
    secrets:
      - db_password
      - db_root_password
    volumes:
      # Volume Docker : persistance des données MariaDB
      - db_data:/var/lib/mysql
    networks:
      - backend
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10

networks:
  frontend:
  backend:

volumes:
  wordpress_data:
  db_data:

secrets:
  db_password:
    file: ./secrets/db_password.txt
  db_root_password:
    file: ./secrets/db_root_password.txt

3. Services et communications

Le fichier déclare trois services. Leurs réseaux et leurs ports déterminent les communications possibles.

ServiceRôle et communications
webUtilise l’image NGINX et appartient à frontend. La déclaration 8080:80 publie son port HTTP : le port 8080 de l’hôte donne accès au port 80 du conteneur.
appUtilise l’image WordPress avec Apache. Il appartient à frontend et backend : NGINX peut le joindre sur app:80, et WordPress peut joindre MariaDB sur db:3306. Aucun de ses ports n’est publié sur l’hôte.
dbUtilise l’image MariaDB et appartient uniquement à backend. Aucun port n’est publié sur l’hôte ; web et db ne partagent aucun réseau.

Les noms app et db servent d’adresses sur les réseaux partagés. Les ports 80 et 3306 sont les ports internes des services, indépendamment du port publié pour NGINX.

Pour approfondir : 7.5 — Réseaux et communication entre services.

4. Configuration et données persistantes

Les trois montages répondent à deux besoins : fournir une configuration depuis l’hôte et conserver les données de l’application.

MontageFonction dans le scénario
Bind mount de web./nginx/default.conf sur l’hôte est monté dans /etc/nginx/conf.d/default.conf. L’option :ro empêche NGINX de modifier ce fichier via le montage.
wordpress_dataCe volume nommé est monté dans /var/www/html pour conserver les fichiers WordPress indépendamment du conteneur app.
db_dataCe volume nommé est monté dans /var/lib/mysql pour conserver les données MariaDB indépendamment du conteneur db.

Le fichier default.conf doit contenir la configuration NGINX qui transmet les requêtes à app:80.
Compose rend ce fichier accessible au conteneur ; le montage seul ne configure pas le reverse proxy.

Les volumes nommés sont déclarés au niveau racine puis référencés sous les services. Ils conservent les données lors du remplacement des conteneurs, tant que les volumes eux-mêmes ne sont pas supprimés.

Pour approfondir : 7.6 — Volumes et persistance des données.

5. Paramètres et accès aux secrets

Les paramètres ordinaires sont transmis avec environment. Les mots de passe sont fournis dans des fichiers secrets accessibles uniquement aux services auxquels ils sont attribués.

DéclarationArticulation dans le scénario
Paramètres dans environmentWordPress reçoit l’adresse db:3306, le nom de base wordpress et le compte wordpress. MariaDB reçoit le nom de base et le compte à créer lors de sa première initialisation.
secrets au niveau racineDéclare db_password et db_root_password, à partir des fichiers ./secrets/db_password.txt et ./secrets/db_root_password.txt sur l’hôte.
secrets sous les servicesapp reçoit uniquement db_password. db reçoit ce même secret et db_root_password. web ne reçoit aucun secret.
Variables _FILELes images WordPress et MariaDB lisent les mots de passe aux chemins indiqués sous /run/secrets/. Le même secret applicatif permet à WordPress d’utiliser le compte configuré dans MariaDB ; le secret root reste réservé à MariaDB.

Les fichiers secrets ne sont pas créés par cette déclaration : ils doivent exister sur l’hôte et rester protégés. Les variables _FILE sont reconnues par les images utilisées dans ce scénario.

Pour approfondir : 7.7 — Configuration, variables et secrets.

6. Ordre de démarrage et disponibilité

Les deux déclarations depends_on n’apportent pas la même garantie.

DéclarationEffet dans le scénario
healthcheck de dbLe contrôle utilise healthcheck.sh pour tester la connexion et l’initialisation d’InnoDB. Il est exécuté toutes les 10s, avec un délai maximal de 5s par contrôle et 10 échecs consécutifs avant de déclarer le conteneur non sain.
app dépend de dbcondition: service_healthy demande à Compose d’attendre que la base soit déclarée saine avant de démarrer WordPress.
web dépend de appLa forme courte depends_on: - app impose le démarrage d’app avant celui de web, mais n’attend pas que WordPress soit prêt à répondre aux requêtes HTTP.

Une base déclarée saine ne garantit donc pas que tout le site est prêt. Ces dépendances de démarrage ne constituent pas une surveillance continue capable de rétablir automatiquement toute l’application.

Pour approfondir : 7.8 — Dépendances et disponibilité des services.

À retenir :

Le fichier Compose rassemble les choix de l’architecture dans une déclaration cohérente :

  • Communications : NGINX est le point d’entrée publié ; WordPress relie les deux réseaux ; MariaDB reste sur backend.
  • Configuration et données : un bind mount fournit la configuration NGINX ; deux volumes nommés conservent les fichiers WordPress et les données MariaDB.
  • Paramètres et secrets : les services reçoivent les paramètres et les fichiers secrets nécessaires à leur rôle.
  • Démarrage : WordPress attend une base saine, mais la disponibilité HTTP de l’ensemble n’est pas garantie par ces seules déclarations.

7.12 Ce qu’il faut retenir

1. Compose et projet

Le fichier compose.yaml décrit la configuration attendue d’une application multi-services

Un projet regroupe ses services et ses ressources.
Docker Engine exécute les conteneurs.


2. Service et conteneur

Un service est une définition
Un conteneur en est une instance.

image désigne l’image à utiliser
build décrit sa construction.


3. Structure

services décrit les composants.

Les réseaux, volumes et secrets déclarés au niveau racine sont référencés par les services qui les utilisent.


4. Réseaux et ports

Les services partageant un réseau peuvent communiquer par leur nom de service et leur port interne.
ports publie un port sur l’hôte

Un service peut appartenir à plusieurs réseaux.


5. Stockage

Un bind mount rend un fichier ou dossier de l’hôte accessible au conteneur
Un volume nommé conserve des données indépendamment du conteneur.

⚠️ La persistance ne remplace pas une sauvegarde.


6. Modes de montage

:ro impose la lecture seule
:rw autorise lecture et écriture au niveau du montage et constitue le mode par défaut.

⚠️ Ces options ne changent pas les permissions des fichiers sur l’hôte.


7. Variables du conteneur

environment les déclare dans le YAML
env_file les fournit depuis un fichier.

Pour une même variable, environment est prioritaire.


8. Interpolation

Compose remplace les expressions ${VARIABLE} à partir de son environnement ou du fichier .env, que --env-file permet de remplacer.

⚠️ Ce fichier n’injecte pas automatiquement toutes ses variables dans les conteneurs.


9. Valeurs attendues

${VARIABLE:-valeur} fournit une valeur par défaut si la variable est absente ou vide
${VARIABLE:?message} exige une valeur non vide.

Les noms des variables du conteneur doivent correspondre à ceux reconnus par l’image ou l’application.


10. Secrets

Ils sont déclarés au niveau racine puis attribués aux services autorisés.
Dans notre scénario, ils sont accessibles sous /run/secrets/

Les variables _FILE indiquent aux images compatibles où les lire.
⚠️ Les fichiers sources sur l’hôte restent à protéger.


11. Démarrage et disponibilité

depends_on exprime les dépendances
healthcheck évalue la santé d’un service.
condition: service_healthy attend un état sain, sans garantir que tout le site est prêt.


12. Cycle de vie

up crée ou actualise et démarre l’application
stop arrête les conteneurs
down supprime les conteneurs et réseaux du projet créés par Compose, sans supprimer les volumes nommés par défaut.


13. Portée

Compose gère une application sur un moteur Docker
Il ne fournit pas à lui seul l’orchestration d’un cluster comparable à Kubernetes.

Documentation officielle : Docker Compose et Compose file reference.

Module 05 · Docker DevOps · Chapitre 7 · v1.5.2-beta-13