Aller au contenu

Docker : faire communiquer deux conteneurs (Apache+PHP+PDO ↔ MariaDB)

Cette fiche résume un exercice qui relie un serveur Apache+PHP à une base MariaDB, via le réseau que Docker Compose crée automatiquement.

Objectif

Reproduire, en conteneurs isolés, ce qu'on pratique en PHP/PDO/MariaDB : un serveur web qui se connecte à une base de données, sans rien installer sur la machine hôte.

Les deux fichiers, dans un même dossier (ex. ~/site-php)

Dockerfile — construit l'image PHP+Apache avec l'extension PDO/MySQL :

FROM php:8.3-apache
RUN docker-php-ext-install pdo pdo_mysql

compose.yaml — orchestre les deux conteneurs :

services:
  db:
    image: mariadb:11
    container_name: db
    environment:
      MARIADB_ROOT_PASSWORD: motdepasseroot
      MARIADB_DATABASE: testdb
      MARIADB_USER: papinou
      MARIADB_PASSWORD: motdepasse
    volumes:
      - db-data:/var/lib/mysql
    restart: unless-stopped

  web:
    build: .
    container_name: web-php
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./:/var/www/html:ro
    depends_on:
      - db
    restart: unless-stopped

volumes:
  db-data:

Important : ce sont deux fichiers distincts, chacun avec son propre contenu, dans le même dossier. Coller le YAML à la suite du Dockerfile (ou l'inverse) produit une erreur de lecture, Docker essayant d'interpréter l'un comme l'autre.

Ce que chaque élément apporte

  • build: . : au lieu d'une image toute prête (image:), compose construit celle décrite par le Dockerfile, dans le dossier courant (.).
  • Le réseau est automatique : compose crée un réseau privé pour tous les services d'un même fichier. À l'intérieur, chaque service est joignable par son nom, sans connaître d'adresse IP :
<?php
$pdo = new PDO('mysql:host=db;dbname=testdb', 'papinou', 'motdepasse');

host=db désigne le service db du fichier, pas une adresse réseau à chercher ailleurs.

  • volumes: db-data:/var/lib/mysql : un volume nommé, géré par Docker (différent d'un simple dossier de la machine comme ~/site-web). Les données de la base survivent à un docker compose down.
  • depends_on: [db] : fait démarrer web après db, mais ne garantit pas que MariaDB soit déjà prête à répondre. Au tout premier démarrage, prévoir quelques secondes d'attente avant de tester la connexion.
  • Les variables MARIADB_* : configurent la base à sa toute première initialisation (nom de la base, utilisateur, mots de passe). À changer dans un vrai projet.

Les commandes

docker compose up -d --build   # construire l'image ET lancer les deux conteneurs
docker compose ps              # vérifier que "db" et "web" sont Up
docker compose logs db         # suivre le démarrage de MariaDB (chercher "ready for connections")
docker compose down            # arrêter, en gardant les données du volume
docker compose down -v         # arrêter, en supprimant aussi les données
docker network ls              # voir le réseau créé (ex. "site-php_default")
docker network inspect NOM     # voir quels conteneurs y sont reliés

Pièges rencontrés en pratique

Symptôme Cause Remède
no configuration file provided: not found compose.yaml absent du dossier courant, ou mal nommé Vérifier avec ls, créer le fichier au bon endroit
unknown instruction: services: dans le Dockerfile Le contenu de compose.yaml a été collé à la suite du Dockerfile, dans le même fichier Séparer les deux fichiers, chacun avec son seul contenu
docker run échoue alors que le Dockerfile vient d'être écrit Le docker build n'a pas été fait avant : docker run cherche une image, pas un Dockerfile. Le Dockerfile n'est qu'une recette, il doit d'abord être transformé en image avant de pouvoir servir à un run docker build -t NOM . avant tout docker run NOM, ou utiliser docker compose up --build qui fait les deux à la suite
Conflit de nom de conteneur (/web-php already in use) Un ancien conteneur du même nom existe encore docker ps -a, puis docker stop et docker rm, ou docker compose down qui le fait automatiquement

Vérifier que les données persistent

docker compose down        # arrête et supprime les conteneurs
docker compose up -d       # relance
# http://127.0.0.1:8080 doit toujours répondre, sans réinitialiser la base

Le volume db-data n'est pas touché par un down/up simple, contrairement aux conteneurs eux-mêmes, qui sont recréés.

Pour la suite

  • Remplacer les mots de passe en dur par un fichier .env, lu via env_file: dans compose.yaml.
  • Ajouter un vrai contrôle de santé (healthcheck:) sur db, pour que web attende réellement que MariaDB soit prête, pas seulement démarrée.
  • Adapter cette structure à deux chemins : un pour un exercice simple avec les élèves, un autre, plus progressif, qui leur fait écrire eux-mêmes le Dockerfile et le compose.yaml une fois les bases acquises.