Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Administration

APERTO-NOTA

Docker Compose et Infrastructure as Code

Jusqu’ici, chaque conteneur était lancé manuellement avec docker run. Cette approche fonctionne pour tester ou découvrir, mais elle pose problème en production : les commandes ne sont pas sauvegardées, l’ordre de démarrage doit être respecté manuellement, et reproduire l’environnement sur une autre machine demande de retaper chaque commande en espérant n’en oublier aucune.

Docker Compose résout ces problèmes en décrivant toute une pile applicative dans un fichier texte docker-compose.yml : services, réseaux, volumes, variables d’environnement, ordre de démarrage. Une seule commande (docker-compose up) suffit ensuite pour déployer l’ensemble, quelle que soit la machine.

Ce principe — décrire une infrastructure dans des fichiers texte plutôt que de l’assembler à la main — s’appelle l’Infrastructure as Code (IaC). Il est au cœur des pratiques modernes d’administration système et DevOps.

Les bénéfices concrets de l’IaC :

Docker Compose est une première étape vers des outils d’IaC plus avancés comme Ansible (configuration de machines), Terraform (provisionnement d’infrastructure cloud) ou Kubernetes (orchestration à grande échelle). Le principe reste le même : l’infrastructure se décrit, ne se clique pas.


Structure d’un fichier docker-compose.yml

Un fichier docker-compose.yml est organisé en quatre sections principales, toutes au même niveau de la hiérarchie YAML.

docker-compose.yaml
services:    # les conteneurs de la pile
volumes:     # les volumes nommés persistants
networks:    # les réseaux virtuels
configs:     # fichiers de configuration injectés (Swarm uniquement)

Balises pouvant être présentes dans docker-compose.yaml

Le format YAML est sensible à l’indentation : utiliser exclusivement des espaces (jamais de tabulations), et respecter scrupuleusement l’alignement.

La section services est la seule obligatoire. Chaque service décrit un conteneur :

docker-compose.yaml
services:

  nom-du-service:            # nom utilisé comme nom DNS sur le réseau
    image: nginx:alpine      # image Docker à utiliser
    container_name: web      # nom du conteneur (optionnel)
    ports:
      - "8080:80"            # port-hote:port-conteneur
    volumes:
      - ./html:/usr/share/nginx/html:ro   # bind mount
      - data-app:/var/lib/mysql           # volume nommé
    networks:
      - reseau-frontend      # réseaux auxquels se connecter
    environment:
      MYSQL_DATABASE: wordpress           # variable d environnement inline
    env_file:
      - .env                 # variables chargées depuis un fichier
    depends_on:
      - db                   # attend que db soit démarré avant
    restart: unless-stopped  # politique de redémarrage

Exemple de docker-compose.yaml

La section volumes déclare les volumes nommés. Un volume déclaré ici est géré par Docker et persiste entre redémarrages :

volumes:
  data-app:     # créé automatiquement au premier docker-compose up
  logs-apache:  # peut être préfixé du nom du projet

Configuration des volumes

La section networks déclare les réseaux. Sans déclaration, Compose crée un réseau par défaut. Avec des réseaux explicites, on contrôle l’isolation :

networks:
  reseau-frontend:
    driver: bridge   # driver par défaut, peut être omis
  reseau-backend:
    driver: bridge

Configuration des réseaux

Commandes essentielles :

CommandeAction
docker-compose up -dDémarrer la pile en mode détaché
docker-compose downArrêter et supprimer les conteneurs et réseaux
docker-compose down -vIdem + supprimer les volumes
docker-compose psÉtat des services
docker-compose logs -f NOMLogs en temps réel d’un service
docker-compose exec NOM CMDExécuter une commande dans un service actif
docker-compose pullMettre à jour les images
docker-compose restart NOMRedémarrer un service sans toucher aux autres

Limiter les ressources CPU et mémoire

Par défaut, un conteneur peut consommer l’intégralité des ressources de l’hôte. En production, il est indispensable de poser des limites pour éviter qu’un service défaillant ne pénalise les autres. C’est le rôle des Cgroups (Control Groups) du noyau Linux, que Docker expose via la clé deploy.resources.

services:

  wordpress:
    image: wordpress:latest
    deploy:
      resources:
        limits:
          cpus: "0.50"       # au maximum 50 % d un coeur CPU
          memory: 512M       # au maximum 512 Mo de RAM
        reservations:
          cpus: "0.25"       # garantis : 25 % d un coeur reserve
          memory: 256M       # garantis : 256 Mo de RAM reserve

  db:
    image: mariadb:10.11
    deploy:
      resources:
        limits:
          cpus: "1.00"       # au maximum 1 coeur complet
          memory: 1G         # au maximum 1 Go de RAM
        reservations:
          memory: 512M

Paramétrage des ressources

CléValeurEffet
limits.cpus"0.50"Le conteneur ne peut pas dépasser 50 % d’un cœur
limits.memory512M, 1GLe conteneur est tué (OOMKill) s’il dépasse cette limite
reservations.cpus"0.25"Docker garantit cette capacité même sous charge
reservations.memory256MMémoire réservée sur l’hôte au démarrage

Docker Compose progressif

Ces exercices reprennent les architectures construites dans les pages précédentes et les traduisent en fichiers docker-compose.yml. L’objectif est de passer du pilotage manuel par docker run à un pilotage déclaratif reproductible.


01. Compose — WordPress + MariaDB sur un réseau personnalisé

Solution to Exercise #

Structure du répertoire :

compose-step1/
  .env
  docker-compose.yml

Les paramètres de configuration de la base de données sont dans un fichier .env.

.env
MYSQL_ROOT_PASSWORD=rootpass
MYSQL_DATABASE=wordpress
MYSQL_USER=wp
MYSQL_PASSWORD=wppass
WORDPRESS_DB_HOST=db
WORDPRESS_DB_USER=wp
WORDPRESS_DB_PASSWORD=wppass
WORDPRESS_DB_NAME=wordpress

Configuration des volumes

Fichier docker-compose.yml :

docker-compose.yaml
services:

  db:
    image: mariadb:10.11
    env_file:
      - .env
    networks:
      - wp-net
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    env_file:
      - .env
    ports:
      - "8080:80"
    networks:
      - wp-net
    depends_on:
      - db
    restart: unless-stopped

networks:
  wp-net:
    driver: bridge

Paramétrage des services

Commandes :

mkdir compose-step1 && cd compose-step1
# Creer .env et docker-compose.yml
docker-compose up -d
docker-compose ps
curl http://localhost:8080 | head -5
docker-compose exec wordpress ping -c 2 db
docker-compose down
cd .. && rm -rf compose-step1

Avantage par rapport à docker run :

docker rundocker-compose
2 commandes séparéesdocker-compose up -d
Ordre manueldepends_on
Réseau créé manuellementDéclaré dans le fichier
Nettoyage en 4 commandesdocker-compose down

02. Compose — WordPress + MariaDB avec volumes séparés et deux réseaux

Solution to Exercise #

Fichier docker-compose.yml :

services:

  db:
    image: mariadb:10.11
    env_file:
      - .env
    volumes:
      - wp-data:/var/lib/mysql    # donnees persistantes
    networks:
      - wp-backend                # backend uniquement : db non accessible depuis frontend
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    env_file:
      - .env
    volumes:
      - wp-logs:/var/log/apache2  # logs Apache
    ports:
      - "8080:80"
    networks:
      - wp-frontend               # reseau web
      - wp-backend                # reseau base de donnees
    depends_on:
      - db
    restart: unless-stopped

volumes:
  wp-data:    # donnees MariaDB
  wp-logs:    # logs Apache

networks:
  wp-frontend:
    driver: bridge
  wp-backend:
    driver: bridge

Vérifier l’isolation réseau :

# db inaccessible depuis wp-frontend
docker-compose exec wordpress ping -c 2 db     # succes : wordpress est sur les deux reseaux
docker run --rm \
  --network compose-step2_wp-frontend \
  alpine ping -c 2 db                          # echec : pas de route vers db

Lire les logs depuis le volume :

docker run --rm \
  -v compose-step2_wp-logs:/logs \
  alpine tail -5 /logs/access.log

Redémarrage sans perte de données :

docker-compose down           # stoppe et supprime les conteneurs, conserve les volumes
docker-compose up -d          # les donnees MariaDB sont intactes
docker-compose down -v        # supprime aussi les volumes

03. Compose — Architecture complète avec Nginx en load balancer

Solution to Exercise #

Structure du répertoire :

compose-final/
  .env
  nginx.conf
  docker-compose.yml

Fichier nginx.conf : (identique à l’exercice final de la page précédente)

Fichier docker-compose.yml :

services:

  db:
    image: mariadb:10.11
    env_file:
      - .env
    volumes:
      - wp-data:/var/lib/mysql
    networks:
      - wp-backend
    restart: unless-stopped

  wordpress:
    image: wordpress:latest
    env_file:
      - .env
    volumes:
      - wp-logs:/var/log/apache2
    networks:
      - wp-frontend
      - wp-backend
    depends_on:
      - db
    # pas de ports : seul nginx est expose
    restart: unless-stopped

  # wordpress2:            # decommenter pour le load balancing
  #   image: wordpress:latest
  #   env_file:
  #     - .env
  #   volumes:
  #     - wp-logs:/var/log/apache2
  #   networks:
  #     - wp-frontend
  #     - wp-backend
  #   depends_on:
  #     - db
  #   restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"                          # seul point d entree
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro  # configuration en bind mount
    networks:
      - wp-frontend
    depends_on:
      - wordpress
    restart: unless-stopped

volumes:
  wp-data:
  wp-logs:

networks:
  wp-frontend:
    driver: bridge
  wp-backend:
    driver: bridge

Commandes :

mkdir compose-final && cd compose-final
# Creer .env, nginx.conf et docker-compose.yml
docker-compose up -d
docker-compose ps
curl http://localhost:8080 | head -5
docker logs compose-final-nginx-1   # logs Nginx
docker-compose down -v
cd .. && rm -rf compose-final

Pour le load balancing (step 4) :

# Decommenter wordpress2 dans docker-compose.yml
# Mettre a jour nginx.conf : ajouter server wordpress2:80
docker-compose up -d --scale wordpress=1   # wordpress2 demarre
docker-compose exec nginx nginx -s reload  # recharger sans interruption

Comparaison des étapes du fil directeur :

ÉtapeArchitectureNouveauté
EX-01 ComposeWordPress + MariaDB, 1 réseauTranslate docker run → Compose
EX-02 Compose+ volumes séparés, 2 réseauxPersistance et isolation
EX-03 Compose+ Nginx LB, N WordPressReverse proxy, load balancing
EX-12 (suivant)Compose complet avec variablesAdministration et cycle de vie

04. Docker Compose : application multi-conteneurs

Solution to Exercise #

Résultat attendu de docker-compose ps :

NAME           IMAGE           SERVICE   STATUS         PORTS
compose-db     mariadb:10.11   db        Up 1 minute    3306/tcp
compose-web    nginx:alpine    web       Up 1 minute    0.0.0.0:8080->80/tcp

Résultat attendu de SHOW DATABASES; :

+--------------------+
| Database           |
+--------------------+
| appdb              |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
SectionRôle
servicesDéfinit chaque conteneur
volumesVolumes nommés partagés
networksRéseaux partagés entre services
depends_onOrdonne le démarrage
env_fileCharge les variables depuis .env
restartPolitique de redémarrage

05. Administration en production

Solution to Exercise #

Résultat attendu de docker inspect sur la politique de redémarrage :

"RestartPolicy": {
    "Name": "unless-stopped",
    "MaximumRetryCount": 0
}

Politiques de redémarrage disponibles :

PolitiqueComportement
no (défaut)Pas de redémarrage automatique
alwaysRedémarre toujours, y compris au boot de l’hôte
unless-stoppedRedémarre sauf si arrêté manuellement
on-failure[:N]Redémarre sur erreur, jusqu’à N fois

Résultat attendu de docker system df :

TYPE            TOTAL   ACTIVE   SIZE      RECLAIMABLE
Images          5       2        312MB     180MB (57%)
Containers      1       1        0B        0B
Local Volumes   1       1        45MB      0B
Build Cache     0       0        0B        0B

06. Swarm : clustering et orchestration

Solution to Exercise #

Résultat attendu de docker node ls :

ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS
abc123def456 *                monhote    Ready     Active         Leader

Résultat attendu après simulation de panne (étape 4) :

ID    NAME        IMAGE          NODE     DESIRED STATE   CURRENT STATE
aaaa  svc-web.1   nginx:alpine   monhote  Running         Running 2 min ago
bbbb  svc-web.2   nginx:alpine   monhote  Running         Running 2 min ago
cccc  svc-web.3   nginx:alpine   monhote  Shutdown        Failed 10 sec ago
dddd  svc-web.3   nginx:alpine   monhote  Running         Running 5 sec ago

Swarm a détecté la disparition du réplica et en a automatiquement créé un nouveau.

Section deploy dans le Compose pour Swarm :

CléRôle
replicasNombre d’instances du service
restart_policyComportement en cas d’échec
update_configStratégie de mise à jour rolling
placement.constraintsContraintes de placement sur les nœuds
ComposeSwarm
Périmètre1 hôteMulti-hôtes
RéplicationNonOui
Load balancingNonIntégré
Haute disponibilitéNonOui
Réseau inter-nœudsbridgeoverlay chiffré