Guide de déploiement

PHP2Shell et Docker : reconstruire vos images PHP et WordPress

Déployer sur un VPS Cloud →

Tutoriel

PHP2Shell et Docker : reconstruire vos images PHP et WordPress

Sécurité & Monitoring12 min de lecture12 étapes

Vous avez mis WordPress à jour la semaine dernière, relancé le conteneur, et vous pensez être couvert contre PHP2Shell. Ce n'est pas certain : dans un conteneur, le PHP vit dans l'image, pas dans l'application, et un redémarrage réutilise l'image déjà présente sur le disque. Les correctifs PHP 8.5.12, 8.4.27, 8.3.36 et 8.2.35 sont sortis le 21 octobre 2026. Ce guide montre comment prouver, conteneur par conteneur, quel PHP répond vraiment, puis comment retirer ou reconstruire l'image qui n'est pas corrigée, pour WordPress, Nextcloud, Laravel Octane et une image maison.

Sommaire· Pourquoi mettre à jour l'application ne change pas le PHP1/14
  1. 01Pourquoi mettre à jour l'application ne change pas le PHP
  2. 02Six objets à ne pas confondre
  3. 03Comparer le registre, l'image locale et le conteneur
  4. 04Lire la version que le web sert vraiment
  5. 05Prouver la version servie, service par service
  6. 06Tags flottants et tags pinnés : qui avance tout seul
  7. 07Quelle écriture avance, laquelle reste figée
  8. 08Image maison : la séquence et ce que chaque option change
  9. 09Reconstruire et recréer une image maison
  10. 10WordPress et Nextcloud officiels : le PHP vient de l'étiquette
  11. 11Laravel Octane et FrankenPHP : le moteur est dans l'image
  12. 12Pièges d'infrastructure qui rejouent l'ancienne image
  13. 13Dépannage : ce que vous voyez, ce que cela veut dire
  14. 14La documentation officielle

Pourquoi mettre à jour l'application ne change pas le PHP

Une mise à jour de WordPress, un composer update ou une nouvelle version de Nextcloud remplacent des fichiers de l'application. L'interpréteur PHP, lui, est un programme installé dans l'image Docker, au même titre que le système Debian ou Alpine qui l'entoure. Tant que l'image ne change pas, le PHP ne change pas, quel que soit le nombre de mises à jour de l'application.

Le second piège est le redémarrage. docker restart relance le conteneur existant, donc la même image. docker compose up -d ne va pas chercher une version plus récente quand une image portant ce nom existe déjà sur le serveur : il réutilise la copie locale. Seul un pull ou un build --pull, suivi d'une recréation du conteneur, change l'interpréteur.

Les deux failles et les commandes apt ou dnf sont détaillées dans notre guide de mise à jour de PHP. Ici, il s'agit de l'image Docker et de la preuve qu'elle est la bonne.

Six objets à ne pas confondre

  • L'image du registre — ce que Docker Hub ou votre registre privé sert aujourd'hui sous une étiquette comme php:8.3-fpm. Une étiquette est mobile : elle pointe vers un autre contenu après chaque reconstruction.
  • L'image locale — la copie présente sur votre serveur, visible avec docker image ls. Elle ne bouge que si vous tirez ou construisez une image.
  • Le conteneur en cours — il garde l'identifiant de l'image avec laquelle il a été créé, même si une image plus récente porte désormais le même nom.
  • Le processus qui répond — PHP-FPM, Apache avec mod_php ou FrankenPHP. C'est lui qui est exposé, et php -v ne l'interroge pas.
  • Les autres services — worker de file, planificateur, conteneur cli de maintenance : chacun a sa propre image, donc sa propre version de PHP.
  • Le cache de construction — une couche FROM en cache peut rejouer l'ancienne base sans qu'aucune erreur ne s'affiche.

Comparer le registre, l'image locale et le conteneur

  1. Lister les images locales et leur date

    docker image ls php (ou wordpress, nextcloud). La colonne CREATED indique quand l'image a été construite. Une image php:8.3-fpm créée avant le 21 octobre 2026 ne contient pas le correctif.

  2. Lire l'image de chaque conteneur

    docker ps affiche dans la colonne IMAGE l'étiquette demandée à la création. Pour obtenir l'identifiant réel de l'image utilisée, interrogez le conteneur : docker inspect --format '{{.Image}}' <conteneur>.

  3. Comparer avec l'image présente sur le disque

    docker image inspect --format '{{.Id}}' php:8.3-fpm rend l'identifiant de l'image qui porte aujourd'hui ce nom. Si cet identifiant diffère de celui du conteneur, le conteneur tourne sur une image plus ancienne que celle du disque : il n'a jamais été recréé après le dernier tirage.

  4. Comparer avec le registre

    docker pull php:8.3-fpm termine par une ligne Status: Downloaded newer image for … quand une image plus récente est arrivée, ou Status: Image is up to date for … sinon. Dans le second cas, soit votre copie est déjà la dernière, soit l'étiquette n'a pas encore été republiée : confrontez-la à la date de l'étiquette sur Docker Hub.

Lire la version que le web sert vraiment

php -v interroge le programme en ligne de commande, pas le processus qui répond aux requêtes. La constante PHP_SAPI dit lequel parle : cli en ligne de commande, fpm-fcgi pour PHP-FPM, apache2handler pour Apache avec mod_php. Dans une image unique, les deux versions coïncident presque toujours. L'écart apparaît dans trois situations courantes avec Docker : un docker compose run démarre un conteneur neuf, donc depuis l'image locale la plus récente, alors que le service web tourne toujours sur l'ancienne ; un conteneur cli de maintenance est bâti sur une autre étiquette que le service web ; un reverse proxy renvoie vers un autre conteneur que celui que vous inspectez.

La preuve la plus fiable reste la requête HTTP : elle suit le chemin d'un visiteur et lit PHP_VERSION dans le processus qui répond. Le binaire FPM se contrôle en complément avec docker exec <conteneur> php-fpm -v.

Prouver la version servie, service par service

  1. Déposer un fichier de test dans le dossier servi

    Exemple avec le service wordpress de l'image officielle, dont le dossier web est /var/www/html (adaptez le service et le chemin à votre stack) : docker compose exec wordpress sh -c 'echo "<?php echo PHP_VERSION, \" \", PHP_SAPI;" > /var/www/html/v-check.php'

  2. L'interroger par HTTP, puis le supprimer aussitôt

    curl -s https://votre-domaine.com/v-check.php puis docker compose exec wordpress rm /var/www/html/v-check.php. La réponse donne la version suivie du SAPI. Comparez-la aux versions corrigées : 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 selon la branche. Un numéro inférieur pour votre branche signifie que le correctif n'est pas là.

  3. Contrôler le binaire FPM du conteneur

    docker exec <conteneur> php-fpm -v affiche la version et le SAPI du binaire FPM de ce conteneur précis. Avec une image Apache, la requête HTTP de l'étape précédente suffit : mod_php est chargé par Apache.

  4. Ne pas se fier à docker compose run

    docker compose run crée un conteneur neuf à partir de l'image locale. Il peut annoncer la version corrigée pendant que le conteneur du site, lui, n'a pas bougé. Contrôlez toujours le conteneur qui reçoit le trafic.

Tags flottants et tags pinnés : qui avance tout seul

Une étiquette de branche comme php:8.3-fpm avance au prochain pull : elle pointe alors vers la version corrigée. Une étiquette exacte comme php:8.3.36-fpm reste sur sa version, et une référence par empreinte (@sha256:…) ne bouge jamais. La documentation de docker image pull est explicite : avec une empreinte, Docker ne récupère aucune reconstruction, correctifs de sécurité compris, tant que vous ne changez pas l'empreinte vous-même.

Les étiquettes corrigées de l'image officielle php sont arrivées sur Docker Hub dans la journée et la soirée du 21 octobre 2026 (UTC), pour les variantes FPM des branches 8.5, 8.4, 8.3 et 8.2. Les images WordPress officielles php8.3-fpm, php8.4-fpm et php8.3-apache ont été republiées le 22 octobre 2026 au petit matin (UTC), et celles de Nextcloud le même jour. Une image tirée avant ces moments est donc l'ancienne, même si son nom est identique. Relisez ces dates sur la page de chaque étiquette. La branche 8.2 reçoit son correctif mais atteint sa fin de vie le 31 décembre 2026 : planifiez son remplacement.

Quelle écriture avance, laquelle reste figée

Faites défiler le tableau

Dans votre compose ou DockerfileAvance au prochain pull ?Pour obtenir le PHP corrigé
`php:8.3-fpm`Oui, l'étiquette est republiée`pull` ou `build --pull`, puis recréer le conteneur
`php:8.3.36-fpm`Non, version exacteDéjà corrigé ; à changer à la main au prochain correctif
`php:8.3.<n>-fpm` avec n inférieur à 36Non, version exactePasser à une étiquette corrigée, reconstruire, recréer
`wordpress:php8.3-fpm`Oui, l'éditeur la republie`pull`, puis recréer le service
`wordpress:<x.y>-php8.3-fpm`Oui pour le PHP : l'éditeur la republie`pull`, puis recréer le service
`php:8.3-fpm@sha256:…`JamaisRemplacer l'empreinte par celle d'une image corrigée
`FROM php:8.3-fpm` dans votre DockerfileSeulement si vous construisez avec `--pull``build --pull`, puis recréer le conteneur
`image: monregistre/app:latest` (votre image)Non, c'est votre dernière constructionReconstruire, republier, puis tirer et recréer

Image maison : la séquence et ce que chaque option change

Pour une image construite chez vous à partir de FROM php:8.3-fpm, la séquence tient en trois commandes : docker compose build --pull --no-cache, puis docker compose up -d --force-recreate, puis le contrôle de la version servie. Chacune répond à un piège précis.

--pull est l'option qui change la version de PHP : elle demande à Docker de chercher une version plus récente de l'image de base au lieu de réutiliser celle du serveur. Sans elle, le FROM est résolu avec la copie locale, et la construction réussit avec l'ancien interpréteur, sans le moindre message.

--no-cache rejoue toutes les couches, y compris apt-get et composer install, ce qui renouvelle aussi les bibliothèques système et les dépendances. Il n'est pas nécessaire pour changer de PHP, car quand l'image de base change, les couches suivantes sont reconstruites d'elles-mêmes. Il sert quand une couche en cache fige un paquet à renouveler.

--force-recreate recrée les conteneurs même si Compose estime que leur configuration et leur image n'ont pas changé. C'est ce qui supprime le doute sur ce qui tourne.

Reconstruire ses images à chaque correctif est un calendrier à tenir, pas un geste unique. Sur un VPS en accès root, ce calendrier est le vôtre, et notre guide d'installation de Docker sur VPS pose la base de travail.

Reconstruire et recréer une image maison

  1. Vérifier que l'étiquette de base est corrigée

    Ouvrez la page de votre étiquette de base sur Docker Hub et vérifiez qu'elle a été publiée à partir du 21 octobre 2026. Si votre FROM vise une version exacte plus ancienne, changez-la d'abord.

  2. Reconstruire en tirant la base

    docker compose build --pull --no-cache. Notez la version avant l'opération avec le fichier de test, pour avoir un avant et un après.

  3. Recréer les conteneurs

    docker compose up -d --force-recreate. Une seule commande peut aussi enchaîner les trois temps : docker compose up -d --build --pull always. Recréez tous les services qui utilisent l'image : web, worker de file, planificateur.

  4. Prouver le résultat

    Relancez le fichier de test, puis comparez l'identifiant donné par docker inspect --format '{{.Image}}' <conteneur> à celui de docker image ls. L'ancienne et la nouvelle image peuvent porter le même nom : seuls l'identifiant et la réponse HTTP font foi.

WordPress et Nextcloud officiels : le PHP vient de l'étiquette

Une étiquette WordPress combine une version de WordPress, une version de PHP et une variante, par exemple php8.3-apache ou php8.3-fpm. La branche PHP est choisie par le nom de l'étiquette. Changer de version de WordPress, ou laisser les mises à jour automatiques agir dans le volume de données, ne touche pas à cette branche. Pour obtenir le PHP corrigé, il faut re-tirer l'étiquette avec docker compose pull, puis recréer le service. La variante Apache est la variante par défaut, et elle charge PHP en mod_php : c'est celle que le projet PHP juge la plus exposée, avec un exploit démontré avant l'exécution du moindre code applicatif. Traitez-la en priorité.

Nextcloud suit le même principe, en deux variantes : apache embarque un Apache complet, fpm demande un serveur web devant lui. La documentation de l'image décrit la mise à jour comme un remplacement : tirer l'image, jeter l'ancien conteneur, démarrer le nouveau. Le code de Nextcloud et vos données vivent dans le volume /var/www/html, que la recréation du conteneur n'efface pas. Voir notre guide WordPress sur VPS et celui de Nextcloud.

Laravel Octane et FrankenPHP : le moteur est dans l'image

Avec Octane et FrankenPHP, il n'y a pas de PHP-FPM : le serveur d'application embarque l'interpréteur. Les images officielles de FrankenPHP reposent sur les images PHP officielles, et leur étiquette combine la version de FrankenPHP, celle de PHP et le système, sous la forme dunglas/frankenphp:<version>-php8.4-trixie. Le projet les reconstruit à chaque version et, chaque jour à 4 h UTC, si de nouvelles images PHP officielles existent. Votre FROM dunglas/frankenphp ne reçoit le correctif que si vous reconstruisez votre image avec --pull.

Le piège propre à Octane est le worker. Octane démarre l'application une fois et la garde en mémoire : php artisan octane:reload relance proprement les workers pour charger le code déployé. C'est le bon geste après un déploiement de code, mais il ne remplace pas l'interpréteur, qui reste celui de l'image en cours. Il en va de même pour un kill -USR2 ou un rechargement de PHP-FPM lancé dans l'ancien conteneur : ils relancent les mêmes fichiers, ceux de l'ancienne image. Pour changer de PHP, recréez le conteneur, y compris ceux des workers de file et du planificateur. Voir notre guide Laravel Octane sur VPS.

Pièges d'infrastructure qui rejouent l'ancienne image

  • Cache de build de la CI — un cache de couches restauré peut rejouer la couche FROM. Ajoutez --pull à la commande de build de la CI, ou invalidez le cache pour cette étape.
  • Registre privé ou miroir — si vos serveurs tirent depuis un registre interne qui copie les images à la main ou par tâche planifiée, vérifiez qu'il a recopié l'étiquette. Sinon pull répond Image is up to date alors que l'éditeur a republié.
  • Stack Portainer ou outil d'orchestration — la mise à jour d'une stack ne re-tire pas toujours l'image. Cochez l'option de re-téléchargement avant le redéploiement si votre outil en propose une.
  • pull_policy: missing — c'est la valeur par défaut de Compose sans section build : il ne tire que si l'image est absente du serveur. Seule l'étiquette latest est tirée dans tous les cas. Utilisez always, ou daily et weekly pour vérifier le registre à intervalle fixe.
  • Un service oublié — web, worker, planificateur et conteneur cli construits depuis des Dockerfile séparés ont chacun leur base : corrigez-les tous.
  • Un conteneur orphelin — un docker run oublié ou un autre projet Compose peut encore répondre sur un port. Listez tout ce qui tourne avec docker ps.

Dépannage : ce que vous voyez, ce que cela veut dire

Faites défiler le tableau

Ce que vous constatezCause probableRemède
`pull` affiche `Status: Image is up to date` mais la version reste ancienneL'étiquette n'a pas encore été republiée, ou vous tirez une version exacte ou une empreinteComparer avec la date de l'étiquette sur Docker Hub, puis passer à une étiquette corrigée
`up -d` ne change rien après un tirageLe conteneur existant n'a pas été recréé`docker compose up -d --force-recreate`, puis comparer les identifiants d'image
Le build se termine en quelques secondes, avec la base déjà en cache`--pull` absent : la base du serveur est réutilisée`docker compose build --pull`, avec `--no-cache` si des paquets système doivent aussi être renouvelés
`docker compose run` annonce la version corrigée, le site répond l'ancienne`run` crée un conteneur neuf, le service web n'a pas été recrééContrôler par HTTP le conteneur qui reçoit le trafic, puis le recréer
La version est bonne mais un worker se comporte comme avantUn worker de file ou Octane tourne encore dans un ancien conteneurRecréer tous les conteneurs qui utilisent l'image, pas seulement le service web

La documentation officielle

Les sources : les annonces de sécurité et de versions de PHP, docker compose up, docker compose build, l'attribut pull_policy, docker image pull, l'image php, l'image wordpress, l'image Nextcloud, FrankenPHP avec Docker et Laravel Octane.

Un VPS où vous tenez vos images et leur calendrier

Sur un VPS ServOrbit.com, vous avez l'accès root et une IPv4 dédiée : vos images Docker, leurs étiquettes et le moment de chaque reconstruction sont les vôtres. Une option d'administration VPS existe aussi ; ses modalités sont décrites sur la page de l'offre.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet