Por qué actualizar la aplicación no cambia PHP
Una actualización de WordPress, un composer update o una nueva versión de Nextcloud sustituyen archivos de la aplicación. El intérprete PHP es un programa instalado en la imagen Docker, igual que el sistema Debian o Alpine que lo rodea. Mientras la imagen no cambie, PHP no cambia, por muchas actualizaciones que reciba la aplicación.
La segunda trampa es el reinicio. docker restart reinicia el contenedor existente, es decir, la misma imagen. docker compose up -d no busca una versión más reciente cuando ya existe en el servidor una imagen con ese nombre: reutiliza la copia local. Solo un pull o un build --pull, seguido de la recreación del contenedor, cambia el intérprete.
Los dos fallos y los comandos apt o dnf se explican en nuestra guía de actualización de PHP. Aquí se trata de la imagen Docker y de la prueba de que es la correcta.
Seis objetos que no deben confundirse
- La imagen del registro — lo que Docker Hub o su registro privado sirve hoy bajo una etiqueta como
php:8.3-fpm. Una etiqueta es móvil: apunta a otro contenido tras cada reconstrucción. - La imagen local — la copia presente en su servidor, visible con
docker image ls. Solo cambia si descarga o construye una imagen. - El contenedor en ejecución — conserva el identificador de la imagen con la que se creó, aunque una imagen más reciente lleve ahora el mismo nombre.
- El proceso que responde — PHP-FPM, Apache con
mod_phpo FrankenPHP. Es el que está expuesto, yphp -vno lo consulta. - Los demás servicios — worker de colas, planificador, contenedor
clide mantenimiento: cada uno tiene su propia imagen y, por tanto, su propia versión de PHP. - La caché de construcción — una capa
FROMen caché puede reproducir la base antigua sin que aparezca ningún error.
Comparar el registro, la imagen local y el contenedor
Listar las imágenes locales y su fecha
docker image ls php(owordpress,nextcloud). La columnaCREATEDindica cuándo se construyó la imagen. Una imagenphp:8.3-fpmcreada antes del 21 de octubre de 2026 no contiene la corrección.Leer la imagen de cada contenedor
docker psmuestra en la columnaIMAGEla etiqueta pedida al crear el contenedor. Para obtener el identificador real de la imagen en uso, consulte el contenedor:docker inspect --format '{{.Image}}' <contenedor>.Comparar con la imagen presente en el disco
docker image inspect --format '{{.Id}}' php:8.3-fpmdevuelve el identificador de la imagen que lleva hoy ese nombre. Si difiere del identificador del contenedor, el contenedor funciona con una imagen más antigua que la del disco: no se recreó tras la última descarga.Comparar con el registro
docker pull php:8.3-fpmtermina con una líneaStatus: Downloaded newer image for …cuando llegó una imagen más reciente, oStatus: Image is up to date for …en caso contrario. En el segundo caso, o bien su copia ya es la última, o bien la etiqueta aún no se ha republicado: contrástela con la fecha de la etiqueta en Docker Hub.
Leer la versión que la web sirve de verdad
php -v consulta el programa de línea de comandos, no el proceso que responde a las peticiones. La constante PHP_SAPI indica cuál habla: cli en línea de comandos, fpm-fcgi para PHP-FPM, apache2handler para Apache con mod_php. En una imagen única, las dos versiones casi siempre coinciden. La diferencia aparece en tres situaciones habituales con Docker: un docker compose run arranca un contenedor nuevo, es decir, desde la imagen local más reciente, mientras el servicio web sigue en la antigua; un contenedor cli de mantenimiento se construyó sobre otra etiqueta que el servicio web; un proxy inverso reenvía a un contenedor distinto del que usted inspecciona.
La prueba más fiable sigue siendo la petición HTTP: sigue el camino de un visitante y lee PHP_VERSION en el proceso que responde. El binario FPM se comprueba como complemento con docker exec <contenedor> php-fpm -v.
Demostrar la versión servida, servicio por servicio
Dejar un archivo de prueba en la carpeta servida
Ejemplo con el servicio
wordpressde la imagen oficial, cuya carpeta web es/var/www/html(adapte servicio y ruta a su stack):docker compose exec wordpress sh -c 'echo "<?php echo PHP_VERSION, \" \", PHP_SAPI;" > /var/www/html/v-check.php'Consultarlo por HTTP y borrarlo enseguida
curl -s https://your-domain.com/v-check.phpy despuésdocker compose exec wordpress rm /var/www/html/v-check.php. La respuesta da la versión seguida del SAPI. Compárela con las versiones corregidas: 8.5.12, 8.4.27, 8.3.36 u 8.2.35 según la rama. Un número inferior para su rama significa que la corrección no está.Comprobar el binario FPM del contenedor
docker exec <contenedor> php-fpm -vmuestra la versión y el SAPI del binario FPM de ese contenedor concreto. Con una imagen Apache basta la petición HTTP del paso anterior: Apache cargamod_php.No fiarse de docker compose run
docker compose runcrea un contenedor nuevo a partir de la imagen local. Puede anunciar la versión corregida mientras el contenedor del sitio no se ha movido. Compruebe siempre el contenedor que recibe el tráfico.
Etiquetas flotantes y fijadas: qué avanza solo
Una etiqueta de rama como php:8.3-fpm avanza en el siguiente pull: pasa a apuntar a la versión corregida. Una etiqueta exacta como php:8.3.36-fpm se queda en su versión, y una referencia por huella (@sha256:…) nunca se mueve. La documentación de docker image pull es explícita: con una huella, Docker no obtiene ninguna reconstrucción, correcciones de seguridad incluidas, hasta que usted cambie la huella.
Las etiquetas corregidas de la imagen oficial php llegaron a Docker Hub durante el día y la noche del 21 de octubre de 2026 (UTC), para las variantes FPM de las ramas 8.5, 8.4, 8.3 y 8.2. Las imágenes oficiales de WordPress php8.3-fpm, php8.4-fpm y php8.3-apache se republicaron el 22 de octubre de 2026 de madrugada (UTC), y las de Nextcloud el mismo día. Una imagen descargada antes de esos momentos es, por tanto, la antigua, aunque el nombre sea idéntico. Compruebe estas fechas en la página de cada etiqueta. La rama 8.2 recibe su corrección pero llega al fin de vida el 31 de diciembre de 2026: planifique su sustitución.
Qué notación avanza y cuál queda congelada
Desplace la tabla
| En su compose o Dockerfile | ¿Avanza en el siguiente pull? | Para obtener el PHP corregido |
|---|---|---|
| `php:8.3-fpm` | Sí, la etiqueta se republica | `pull` o `build --pull`, y recrear el contenedor |
| `php:8.3.36-fpm` | No, versión exacta | Ya corregida; cámbiela a mano en la siguiente corrección |
| `php:8.3.<n>-fpm` con n inferior a 36 | No, versión exacta | Pasar a una etiqueta corregida, reconstruir, recrear |
| `wordpress:php8.3-fpm` | Sí, el mantenedor la republica | `pull` y recrear el servicio |
| `wordpress:<x.y>-php8.3-fpm` | Sí para PHP: el mantenedor la republica | `pull` y recrear el servicio |
| `php:8.3-fpm@sha256:…` | Nunca | Sustituir la huella por la de una imagen corregida |
| `FROM php:8.3-fpm` en su Dockerfile | Solo si construye con `--pull` | `build --pull` y recrear el contenedor |
| `image: miregistro/app:latest` (su imagen) | No, es su última construcción | Reconstruir, republicar, descargar y recrear |
Imagen propia: la secuencia y lo que cambia cada opción
Para una imagen construida en casa a partir de FROM php:8.3-fpm, la secuencia son tres comandos: docker compose build --pull --no-cache, luego docker compose up -d --force-recreate, y por último la comprobación de la versión servida. Cada uno responde a una trampa concreta.
--pull es la opción que cambia la versión de PHP: pide a Docker que busque una versión más reciente de la imagen base en lugar de reutilizar la del servidor. Sin ella, el FROM se resuelve con la copia local y la construcción termina con el intérprete antiguo, sin un solo mensaje.
--no-cache reejecuta todas las capas, incluidas apt-get y composer install, lo que renueva también las bibliotecas del sistema y las dependencias. No hace falta para cambiar de PHP, porque cuando cambia la imagen base las capas siguientes se reconstruyen solas. Sirve cuando una capa en caché congela un paquete que quiere renovar.
--force-recreate recrea los contenedores aunque Compose considere que su configuración y su imagen no han cambiado. Así se elimina la duda sobre lo que está en marcha.
Reconstruir sus imágenes con cada corrección es un calendario que mantener, no un gesto único. En un VPS con acceso root, ese calendario es suyo, y nuestra guía para instalar Docker en un VPS sienta la base de trabajo.
Reconstruir y recrear una imagen propia
Comprobar que la etiqueta base está corregida
Abra la página de su etiqueta base en Docker Hub y compruebe que se publicó a partir del 21 de octubre de 2026. Si su
FROMapunta a una versión exacta más antigua, cámbiela primero.Reconstruir descargando la base
docker compose build --pull --no-cache. Anote la versión antes de la operación con el archivo de prueba, para tener un antes y un después.Recrear los contenedores
docker compose up -d --force-recreate. Un solo comando puede encadenar los tres tiempos:docker compose up -d --build --pull always. Recree todos los servicios que usan la imagen: web, worker de colas, planificador.Demostrar el resultado
Vuelva a ejecutar el archivo de prueba y compare el identificador dado por
docker inspect --format '{{.Image}}' <contenedor>con el dedocker image ls. La imagen antigua y la nueva pueden llevar el mismo nombre: solo el identificador y la respuesta HTTP hacen fe.
WordPress y Nextcloud oficiales: el PHP viene de la etiqueta
Una etiqueta de WordPress combina una versión de WordPress, una versión de PHP y una variante, por ejemplo php8.3-apache o php8.3-fpm. La rama de PHP la elige el nombre de la etiqueta. Cambiar la versión de WordPress, o dejar que las actualizaciones automáticas actúen en el volumen de datos, no toca esa rama. Para obtener el PHP corregido hay que volver a descargar la etiqueta con docker compose pull y recrear el servicio. La variante Apache es la predeterminada y carga PHP como mod_php: es la que el proyecto PHP considera más expuesta, con un exploit demostrado antes de que se ejecute código de la aplicación. Trátela con prioridad.
Nextcloud sigue el mismo principio, en dos variantes: apache incluye un Apache completo, fpm necesita un servidor web delante. La documentación de la imagen describe la actualización como un reemplazo: descargar la imagen, tirar el contenedor antiguo, arrancar el nuevo. El código de Nextcloud y sus datos viven en el volumen /var/www/html, que la recreación del contenedor no borra. Vea también nuestra guía de WordPress en VPS y la de Nextcloud.
Laravel Octane y FrankenPHP: el motor está en la imagen
Con Octane y FrankenPHP no hay PHP-FPM: el servidor de aplicaciones incorpora el intérprete. Las imágenes oficiales de FrankenPHP se basan en las imágenes oficiales de PHP, y su etiqueta combina la versión de FrankenPHP, la de PHP y el sistema, con la forma dunglas/frankenphp:<version>-php8.4-trixie. El proyecto las reconstruye en cada versión y, cada día a las 4 h UTC, si existen nuevas imágenes oficiales de PHP. Su FROM dunglas/frankenphp solo recibe la corrección si reconstruye su imagen con --pull.
La trampa propia de Octane es el worker. Octane arranca la aplicación una vez y la mantiene en memoria: php artisan octane:reload reinicia con cuidado los workers para cargar el código desplegado. Es el gesto correcto tras un despliegue de código, pero no sustituye al intérprete, que sigue siendo el de la imagen en curso. Lo mismo ocurre con un kill -USR2 o una recarga de PHP-FPM lanzada en el contenedor antiguo: relanzan los mismos archivos, los de la imagen antigua. Para cambiar de PHP, recree el contenedor, incluidos los de los workers de colas y el planificador. Vea nuestra guía de Laravel Octane en VPS.
Trampas de infraestructura que reproducen la imagen antigua
- Caché de build de la CI — una caché de capas restaurada puede reproducir la capa
FROM. Añada--pullal comando de build de la CI, o invalide la caché en ese paso. - Registro privado o espejo — si sus servidores descargan de un registro interno que copia las imágenes a mano o con una tarea programada, compruebe que copió la etiqueta. Si no,
pullrespondeImage is up to dateaunque el mantenedor haya republicado. - Stack de Portainer o herramienta de orquestación — actualizar un stack no siempre vuelve a descargar la imagen. Marque la opción de nueva descarga antes de redesplegar si su herramienta la ofrece.
pull_policy: missing— es el valor predeterminado de Compose sin secciónbuild: solo descarga si la imagen no está en el servidor. Solo la etiquetalatestse descarga siempre. Usealways, odailyyweeklypara consultar el registro a intervalos fijos.- Un servicio olvidado — web, worker, planificador y contenedor
cliconstruidos desde Dockerfile distintos tienen cada uno su base: corríjalos todos. - Un contenedor huérfano — un
docker runolvidado u otro proyecto Compose puede seguir respondiendo en un puerto. Liste todo lo que está en marcha condocker ps.
Solución de problemas: lo que ve y lo que significa
Desplace la tabla
| Lo que observa | Causa probable | Remedio |
|---|---|---|
| `pull` muestra `Status: Image is up to date` pero la versión sigue siendo antigua | La etiqueta aún no se ha republicado, o descarga una versión exacta o una huella | Comparar con la fecha de la etiqueta en Docker Hub y pasar a una etiqueta corregida |
| `up -d` no cambia nada tras una descarga | El contenedor existente no se recreó | `docker compose up -d --force-recreate` y comparar los identificadores de imagen |
| El build termina en pocos segundos, con la base ya en caché | Falta `--pull`: se reutiliza la base del servidor | `docker compose build --pull`, con `--no-cache` si también hay que renovar paquetes del sistema |
| `docker compose run` anuncia la versión corregida, el sitio responde la antigua | `run` crea un contenedor nuevo, el servicio web no se recreó | Comprobar por HTTP el contenedor que recibe el tráfico y recrearlo |
| La versión es correcta pero un worker se comporta como antes | Un worker de colas o de Octane sigue en un contenedor antiguo | Recrear todos los contenedores que usan la imagen, no solo el servicio web |