A container has its own PHP, separate from the server it runs on. Updating PHP on the server does not change PHP in your containers. And a container keeps running the image it was started with until you replace it, even after a newer image exists.
Check which PHP a container runs#
-
List your containers and the images they use:
docker ps --format 'table {{.Names}}\t{{.Image}}' -
Check the PHP version inside a container. Replace
my-appwith the container name:docker exec my-app php -v -
In an image with PHP-FPM, check that too:
docker exec my-app php-fpm -v
With Docker Compose, use the service name: docker compose exec app php -v.
Know which tag your image follows#
The tag after the colon decides what you get when you pull. For the official php image:
| Tag | What you get |
|---|---|
php:8.3-fpm |
the newest 8.3 release, updated when PHP releases a new 8.3 |
php:8.3.36-fpm |
exactly 8.3.36, never anything newer |
php:fpm or php:latest |
the newest branch, which can jump from 8.4 to 8.5 |
A tag with the full version number never gets security fixes. To update, you change the number.
For an image someone else built (for your app, or a base image from another maintainer), the PHP inside comes from that maintainer. Check their release notes or the PHP version in their newest image before you rely on it.
Update a container that uses an image as it is#
Use this when your docker-compose.yml has an image: line and no build:.
-
Change the tag if it has a full version number, for example from
php:8.3.30-fpmtophp:8.3.36-fpm. -
Download the new image:
docker compose pull -
Recreate the containers with the new image:
docker compose up -d -
Check the version again:
docker compose exec app php -v.
Without Compose, docker pull the image, then stop and remove the old container and start a new one with the same options. Make sure its data is in a volume or bind mount first, or it is lost with the container.
Rebuild an image you build yourself#
Use this when you have a Dockerfile that starts with something like FROM php:8.3-fpm.
-
If the
FROMline has a full version number, raise it. -
Build again, and make Docker download the newest base image instead of using the copy it has:
docker compose build --pullWithout Compose:
docker build --pull -t my-app . -
Recreate the containers:
docker compose up -d -
Check the version inside the new container.
Settings for PHP in the official image#
In the official php image, extra ini files go in $PHP_INI_DIR/conf.d/ (that is /usr/local/etc/php/conf.d/). To add a setting, for example the emergency measure from PHP2Shell: patch CVE-2026-109618 and CVE-2026-109619, add a line to your Dockerfile:
RUN echo 'session.upload_progress.enabled = 0' > "$PHP_INI_DIR/conf.d/99-emergency.ini"
Then rebuild and recreate the container as above. A file you only change inside a running container is gone at the next recreate.
Clean up old images#
Old images stay on disk after an update. When you pull a newer image under the same tag, the old one loses its tag. To remove images without a tag:
docker image prune
It asks for confirmation first. docker image prune -a goes further and removes every image no container uses; only run that if you are sure you do not need them.