Aller au contenu
Développement medium

PHP pour les ops : déployer et exploiter

10 min de lecture

PHP fait tourner une large part du web (WordPress, Laravel, Symfony, Drupal), et l'exploiter en production ne demande pas de savoir coder en PHP, mais de comprendre comment il s'exécute. Ce guide s'adresse aux ops : versions et support, le modèle php-fpm, Composer pour les dépendances, OPcache pour la performance, le déploiement en conteneur et le durcissement de php.ini. Commandes validées sur PHP 8.5.

  • Suivre les versions de PHP et leur fin de support
  • Comprendre php-fpm et le rôle du serveur web
  • Déployer une application PHP avec Composer et OPcache
  • Durcir une installation PHP en production

PHP suit un cycle clair : 2 ans de support actif (bugs + sécurité) puis 2 ans de support sécurité seul, soit 4 ans par branche. En production, ne jamais faire tourner une branche en fin de vie (EOL), qui ne reçoit plus de correctifs.

BrancheSupport actifSécurité jusqu'à
8.2terminé31 déc. 2026
8.3terminé31 déc. 2027
8.4jusqu'au 31 déc. 202631 déc. 2028
8.5 (stable)jusqu'au 31 déc. 202731 déc. 2029

Point de vigilance : PHP 8.2 sort du support sécurité fin 2026, et tout ce qui précède 8.2 est déjà EOL. Planifiez les montées de version comme une tâche d'exploitation, pas comme une option.

C'est le point que tout ops doit saisir : PHP n'est pas un serveur web, c'est un interpréteur que le serveur web appelle. Deux modèles existent :

  • mod_php (ancien) : PHP est embarqué dans Apache. Simple, mais chaque process Apache porte un interpréteur PHP, ce qui consomme.
  • php-fpm (recommandé) : FastCGI Process Manager. Le serveur web (Nginx ou Apache) reçoit la requête HTTP et la transmet à un pool de processus php-fpm via le protocole FastCGI. C'est plus léger, plus configurable, et c'est le standard moderne.

Le dimensionnement de php-fpm se joue sur le pool de workers, réglé par la directive pm :

  • static : un nombre fixe de workers (pm.max_children).
  • dynamic : un nombre piloté entre un minimum et un maximum.
  • ondemand : aucun worker au repos, créés à la demande.

Le paramètre critique est pm.max_children : il fixe le nombre de requêtes simultanées servies. La règle mémoire est directe : max_children × empreinte d'un worker doit tenir dans la RAM disponible. Trop haut, le serveur swappe ; trop bas, les requêtes attendent.

; /etc/php/8.5/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500 ; recycle un worker après 500 requêtes (fuites mémoire)

Composer est le gestionnaire de dépendances de PHP. Deux fichiers gouvernent un projet :

  • composer.json : les dépendances déclarées.
  • composer.lock : les versions exactes verrouillées, à committer dans le dépôt pour des installations reproductibles.

En production, la commande à retenir installe les dépendances depuis le lock, sans les outils de développement, avec un autoloader optimisé :

Fenêtre de terminal
composer install --no-dev --optimize-autoloader

--no-dev saute les paquets de require-dev (tests, debug) ; --optimize-autoloader génère un classmap qui accélère le chargement des classes. N'utilisez jamais composer update en production : il recalcule les versions et casse la reproductibilité.

Sans cache, PHP recompile chaque fichier à chaque requête. OPcache met le bytecode compilé en mémoire partagée : c'est le gain de performance le plus important, et il est indispensable en production.

opcache.enable=1
opcache.memory_consumption=256 ; Mo de cache (défaut 128)
opcache.max_accelerated_files=20000 ; nombre de fichiers en cache
opcache.validate_timestamps=0 ; prod immuable : ne pas vérifier les dates

opcache.validate_timestamps=0 supprime la vérification des fichiers à chaque requête (gain net), à condition de recharger OPcache à chaque déploiement, sinon l'ancien code reste servi. C'est exactement le rôle du reload de php-fpm ci-dessous.

Un déploiement type enchaîne le code, les dépendances, les migrations, puis un rechargement gracieux de php-fpm :

Fenêtre de terminal
git pull # ou un artefact versionné
composer install --no-dev --optimize-autoloader
php bin/console doctrine:migrations:migrate # migrations (framework-dépendant)
sudo systemctl reload php8.5-fpm # recharge sans couper les requêtes en cours

Le reload exploite la gestion gracieuse des process de php-fpm : les requêtes en cours se terminent, les nouvelles partent sur le code à jour. Avec validate_timestamps=0, ce reload est obligatoire pour que le nouveau code soit pris en compte.

En conteneur, l'image officielle se décline en php:8.5-cli, php:8.5-fpm et php:8.5-apache. La variante -fpm est la bonne pour la production, mais elle exige un reverse proxy : le protocole FastCGI ne doit jamais être exposé publiquement (la doc officielle le qualifie d'« extrêmement non sécurisé » hors réseau privé). Le pattern standard est donc deux conteneurs : un nginx public, un php-fpm privé, sur un réseau Docker interne.

Quelques directives php.ini réduisent nettement la surface d'attaque :

expose_php=Off ; masque "X-Powered-By: PHP/8.5" dans les en-têtes
display_errors=Off ; ne jamais afficher d'erreur au visiteur
log_errors=On ; les logger côté serveur à la place
open_basedir=/var/www/app:/tmp
disable_functions=exec,passthru,shell_exec,system,proc_open,popen
  • expose_php=Off retire la version de PHP des en-têtes HTTP, une information offerte aux scanners.
  • display_errors=Off évite de divulguer chemins et traces ; on logge à la place.
  • open_basedir et disable_functions sont des filets de sécurité (la doc officielle prévient qu'ils sont contournables), pas des garanties : à compléter, jamais à considérer comme suffisants. Adaptez disable_functions à votre application, car certaines en ont légitimement besoin.
  • La meilleure mesure reste de tenir PHP à jour : une branche EOL est un risque permanent.

Quelques commandes confirment l'état d'une installation, en local comme en conteneur :

Fenêtre de terminal
php -v # version + SAPI
php -m # extensions chargées
php -l app.php # lint d'un fichier (syntaxe)
php-fpm -t # test de la configuration php-fpm

Sorties réelles sur PHP 8.5 :

PHP 8.5.7 (cli) (built: Jun 24 2026) (NTS)
No syntax errors detected in app.php
NOTICE: configuration file /usr/local/etc/php-fpm.conf test is successful

En production, display_errors=Off masque les erreurs au visiteur : il faut donc savoir où elles partent. Trois sources à connaître :

  • Erreurs PHP : la directive error_log de php.ini indique le fichier (ou syslog) où PHP écrit, à condition que log_errors=On.
  • php-fpm : chaque pool a son error_log, et surtout un slowlog qui enregistre les requêtes dépassant un seuil, l'outil idéal pour traquer une page lente.
; pool php-fpm
slowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 5s ; trace toute requête > 5 secondes
  • En conteneur : les logs doivent partir sur la sortie standard (stdout/stderr) pour être captés par Docker ou Kubernetes, et non dans un fichier perdu à l'intérieur du conteneur.

Quand un site PHP ralentit, le réflexe est de croiser le slowlog php-fpm (quelle requête) avec le nombre de workers occupés (pm.status_path expose un état du pool) : on voit vite si le problème vient du code ou d'un sous-dimensionnement de pm.max_children.

  • PHP suit un cycle de 4 ans par branche ; 8.5 est la stable, 8.2 sort du support sécurité fin 2026. Ne tournez jamais en EOL.
  • php-fpm (FastCGI) derrière Nginx est le modèle moderne ; pm.max_children dimensionne les requêtes simultanées et la RAM.
  • En prod : composer install --no-dev --optimize-autoloader, jamais update.
  • OPcache est indispensable ; avec validate_timestamps=0, rechargez php-fpm à chaque déploiement.
  • En conteneur : php:8.5-fpm derrière un Nginx, FastCGI jamais exposé ; secrets par variables d'environnement.
  • Durcir php.ini : expose_php=Off, display_errors=Off, open_basedir, disable_functions (filets, pas garanties).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn