Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

Patching PHP in Docker Containers

Containers do not patch themselves. Against PHP2Shell you have to rebuild or re-pull the PHP image and recreate every container from the new image.

Last updated 5 min readPHP2Shell

In short: Updating the PHP Docker image is mandatory against PHP2Shell, and it does not happen by itself. You have to rebuild or pull the image with a fixed PHP version, recreate every container from it and verify that 8.5.12, 8.4.27, 8.3.36 or 8.2.35 is running in the live container. A simple container restart is not enough.

Why containers are not automatically secure

A Docker image is a frozen snapshot. The PHP inside stays at the state it had when the image was built, even if updates were long ago installed on the host. A package update on the host system changes nothing about the PHP in the container.

Typical pitfalls add to this: images that were built months ago and not touched since, base images with a fixed tag such as php:8.3.35-fpm, local caches that reuse the old base image during the build, and containers that were restarted but never recreated. All operating modes that are common in containers are affected: PHP-FPM, Apache with mod_php and FrankenPHP.

There is also a question of responsibility. In many companies, an agency or developer built the image once, but it is operated by the internal IT team or a hosting provider. Then nobody feels responsible for the PHP version in the image. So first clarify who builds the image, where the Dockerfile is kept and who may roll out new images.

Checking the PHP version in the container

Check the running container, not just the Dockerfile. The commands are read-only.

docker ps --format "table {{.Names}}\t{{.Image}}\t{{.CreatedAt}}"
docker exec <container> php -v
docker exec <container> php -i | grep -E "^PHP Version|Server API"
docker image inspect <image> --format "{{.Created}}"

If the image uses distribution packages instead of official PHP builds, check the package version in the container. Package names differ by base distribution:

docker exec <container> sh -c "apt policy php8.3-fpm 2>/dev/null || apk info -v 2>/dev/null | grep php"

With distribution packages, a backport may be applied although the version number stays old. In that case the package changelog counts. The official PHP images, by contrast, usually ship PHP compiled by themselves; there the version number from php -v is the decisive value. How to recognise backports is described in Checking the PHP version and patch level correctly.

Updating the PHP Docker image: rebuild and roll out

Your own image based on a PHP image: pull the base image again and build without cache.

docker build --pull --no-cache -t meine-app:2026-10-25 .
docker run --rm meine-app:2026-10-25 php -v      # check the version before rolling out

With Docker Compose: pull or build images and recreate containers.

docker compose pull
docker compose build --pull --no-cache
docker compose up -d --force-recreate

Afterwards check again with docker exec <container> php -v that the new version is running. If the container has a fixed version tag in the Dockerfile, for example FROM php:8.3.35-fpm, you have to raise the tag. A tag on the branch such as php:8.3-fpm receives new patch versions, but only if you pull again.

Keep the previous image ready until the new version has been tested. In case of an error you can then switch back without leaving the application offline for long. The old image, however, contains the vulnerable PHP again; a rollback is therefore only defensible briefly and together with the interim measures.

If you use Kubernetes, you roll out the new image through the deployment. Details are at Patching PHP in Kubernetes. The same procedure applies to FrankenPHP images; notes on the operating mode can be found at Securing FrankenPHP.

Important

Do not forget side containers: cron and queue workers, admin tools or staging environments often use the same PHP image but run in their own containers. Every one of them must be recreated.

Interim measures in the container

If the update is not yet possible, the interim measures from php.net also apply in the container. They are not full protection. The memory limit belongs on the container, because php.net recommends it via container or cgroup, not via RLIMIT_AS or RLIMIT_DATA:

; e.g. as a file in the image: /usr/local/etc/php/conf.d/zz-uebergang.ini
memory_limit = -1
post_max_size = 8M
upload_max_filesize = 6M
session.upload_progress.enabled = 0
docker run --memory=1g ...         # or in Compose: deploy.resources.limits.memory

You adjust the value to your application. Make sure the application cannot override memory_limit itself; with PHP-FPM, you set the values for this in the pool with php_admin_value. New configuration only takes effect once the container has been recreated or restarted; the background on restarting is explained at Restarting PHP-FPM and all workers.

So that it goes faster next time

  • Rebuild images regularly and automatically, not only on code changes.
  • Use base images with a branch tag and version the built state with a date or digest.
  • Have images scanned for known vulnerabilities before rollout and run containers without root rights.
  • Keep an inventory of which containers use which image.

How does PHP SOS help?

  • Take stock: We check all running containers, their images and PHP versions, including side containers and staging.
  • Rebuild and roll out: Through the PHP patch service, we build the images with the fixed version and recreate the containers in a controlled way.
  • Secure the transition where the update depends on the application: php.net values, memory limit on the container.
  • Monitor permanently: With security monitoring, we keep an eye on image versions and unusual container behavior.

Frequently asked questions

Is docker restart enough after the update?

No. docker restart restarts the container with the same, old image. You have to build or pull the new image and recreate the container from it, for example with docker compose up -d --force-recreate.

Does the official PHP image already contain the fixed version?

It is best to check this directly: pull the image again and run php -v inside it. Expected are 8.5.12, 8.4.27, 8.3.36 or 8.2.35. If the image shows an older number, it has not been updated yet or comes from a cache.

Is PHP in a container less at risk than on the host?

The vulnerability itself works the same in a container. A well-built container can limit the consequences of a break-in, for example through a non-root user and a read-only file system. It does not replace the patch.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help