Objectif
- Montrer comment s’articule le ballet PHP-FPM - Nginx afin de répondre aux requêtes web dans un environnement dockerisé, tout cela à travers notre reverse proxy Traefik
Introduction
La spécificité de PHP-FPM PHP-FPM (FastCGI Process Manager)
Le point clé réside dans l’approche architecturale de PHP.
Méthode traditionnelle: Dans une configuration traditionnelle (par exemple, Apache avec mod_php), le serveur web et l’interpréteur PHP ne forment qu’un seul processus monolithique. À chaque nouvelle requête web, un nouveau processus Apache est créé, lequel contient l’intégralité du moteur PHP. Cette approche est simple à mettre en place, mais elle consomme beaucoup de ressources et n’est pas très efficace pour gérer un grand nombre de requêtes.
Méthode PHP-FPM: PHP-FPM sépare les responsabilités. Le serveur web (Nginx) est optimisé pour ce qu’il fait de mieux (servir des fichiers), et PHP-FPM est un pool de processus distinct et dédié, optimisé pour l’exécution de PHP. Cette approche permet à chaque composant d’être extrêmement performant et évolutif. En cas de forte charge, vous pouvez simplement augmenter la capacité du service PHP-FPM sans affecter le serveur web. Cette méthode est bien plus efficace et résiliente pour les applications web modernes.
Le Request Flow
Une requête arrive dans Traefik sur le port 443 (HTTPS), qui la déchiffre et l’envoie à Nginx. Nginx, agissant comme un proxy, transfère la requête à PHP-FPM via un réseau interne privé. PHP-FPM exécute le code, renvoie le résultat à Nginx, et Nginx transmet le contenu final à Traefik, qui le chiffre à nouveau et le délivre à l’utilisateur. Comme illustré dans le diagramme suivant.
Vue d'ensemble du workflow Docker - Traefik - Nginx - PHP-FPM
Source code
Vous trouverez ici le code source d’une page de démonstration PHP simple, montrant comment les différents conteneurs fonctionnent ensemble pour gérer les requêtes: https://github.com/a-naitslimane/anaitslimane.article.php-fpm-traefik-docker
Setup
Prérequis:
- Docker et Docker Compose installés sur votre machine
- Un reverse proxy Traefik dockerisé tournant en local. Si vous ne l’avez pas déjà, veuillez vous réferer à mon précédent article Traefik reverse proxy
Important!
Les configurations suivantes sont fortement liées aux configurations de mon précédent article. N’oubliez pas de les ajuster avec vos propres valeurs, en particulier le nom de réseau docker externe
Configuration locale
-
Cloner le code source dans votre répertoire de travail
-
Définir les variables d’environnement
- Créez une copie de .env.exemple nommée .env.
Vous pouvez y définir vos propres valeurs, bien sûr, à condition qu’elles soient cohérentes avec le reste de la configuration.\
- Créez une copie de .env.exemple nommée .env.
-
Lier votre DOMAIN_NAME au localhost:
-
Ajoutez votre domaine local au fichier
hosts:C:\Windows\System32\drivers\etc\hosts(sous Windows) et/etc/hosts(sous Linux).127.0.0.1 php-fpm.demo.domain
-
-
Lancer les services avec docker compose:
- Dans votre terminal, placez-vous dans votre répertoire de travail et exécutez:
docker compose -f docker-compose.yaml -f up
- Dans votre terminal, placez-vous dans votre répertoire de travail et exécutez:
Tests
-
Vérifiez que les conteneurs nginx et php-fpm sont en cours d’exécution et en bonne santé.
-
Ouvrez l’adresse que vous aviez configuré en tant que DOMAIN_NAME dans votre navigateur web (ex: https://php-fpm.demo.domain )
Vous devriez avoir cette page:
Analyse
-
Les réseaux Docker sont définis ici:
## docker-compose.yaml ##3networks: 4 my-external-network: 5 external: true 6 my-internal-network: 7 external: false -
Le my-external-network est le seul exposé à l’extérieur et est utilisé par le conteneur nginx pour communiquer avec Traefik:
## docker-compose.yaml ##9services: 10 nginx: 11 image: nginx:alpine 12 container_name: nginx 13 volumes: 14 # Mount the application source code into the Nginx container. 15 - ./public:/var/www/html 16 # Mount the custom Nginx configuration file. 17 - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro 18 networks: 19 - my-external-network 20 - my-internal-network -
L’autre réseau (my-internal-network) est propre aux deux conteneurs nginx et php-fpm et sert uniquement à ces derniers pour communiquer entre-eux:
## docker-compose.yaml ##31 php-fpm: 32 image: php:8.3-fpm-alpine 33 container_name: php-fpm 34 volumes: 35 # Mount the application source code into the PHP-FPM container. 36 - ./public:/var/www/html 37 networks: 38 - my-internal-network -
Dans la configuration de Nginx suivante, la ligne clé est en surbrillance. Elle indique quel hôte Docker doit recevoir les requêtes .php et sur quel port
## default.conf ##14 # This location block specifically handles files ending in .php. 15 location ~ \.php$ { 16 # Ensure the file exists to prevent arbitrary code execution. 17 try_files $uri =404; 18 19 # Pass the request to the PHP-FPM service. 20 fastcgi_pass php-fpm:9000; -
Voici un test simple montrant que php-fpm est configuré pour traiter les requêtes
## index.php ##54 <?php 55 ob_start(); 56 phpinfo(); 57 $php_info = ob_get_clean(); 58 59 $lines = explode("\n", $php_info); 60 foreach ($lines as $line) { 61 if (strpos($line, 'Server API') !== false) { 62 echo htmlspecialchars($line); 63 break; 64 } 65 } 66 ?>
Pour conclure
La mise en place d’une stack web moderne avec Docker, Traefik, Nginx et PHP-FPM est une approche puissante pour construire une application robuste et évolutive. Elle représente un changement fondamental, passant des serveurs web monolithiques tout-en-un à une architecture plus efficace et découplée.
Cette séparation des responsabilités est l’avantage clé. Elle vous permet de faire évoluer chaque partie de votre application de manière indépendante, garantissant ainsi que votre site web reste performant et résilient en cas de forte charge.