PHP2Shell-fixed PHP images: php-fpm 7.3-prod / 7.4-prod / 8.2-prod and php 7.3-apache (nimasystems fork)
This fork publishes devilbox/php-fpm 7.3-prod, 7.4-prod and 8.2-prod and the official php:7.3-apache with PHP
rebuilt to fix PHP2Shell: CVE-2026-109618
(RCE via OOM corruption) and CVE-2026-109619
(RCE via stale global state), both CVSS 9.2.
PHP 8.2 got an official release with the fix (8.2.35), so the 8.2 image is simply upgraded from the PHP 8.2.1
it shipped with. PHP 7.3 and 7.4 are end of life and have no official release with the fix. The PHP security team
published a minimal source backport for EOL branches (PHP-7.4-CVE-2026-109618-109619,
commit 712e60f9edfd):
| Image | PHP | Patch |
|---|---|---|
7.4-prod |
7.4.33 | official backport, unmodified |
7.3-prod |
7.3.33 | official backport ported to 7.3 (differences listed in the patch header) |
8.2-prod |
8.2.35 | official release (upgraded from 8.2.1), checksum pinned in Dockerfile-8.2 |
php:7.3-apache |
7.3.33 | same 7.3 patch, built as the Apache module (libphp7.so, mod_php) and CLI (Dockerfile-7.3-apache) |
The 7.3 / 7.4 patch (8.2.35 contains the complete upstream fix, which handles OOM gracefully instead):
- replaces the
longjmp()bailout on memory-limit / allocation-overflow errors with an immediate_exit()of the worker, so request shutdown never runs on half-initialized state - resets error, exception, object-store, HTTP globals, SAPI and session state at request shutdown so nothing stale is visible to the next request
- limits multipart parsing (
max_multipart_body_parts, defaultmax_input_vars + max_file_uploads; onlyContent-Disposition/Content-Typepart headers are kept) - disables the session upload progress hook (
session.upload_progress.enabledis also set toOff)
Behavior change (7.3 / 7.4 only): a request that hits memory_limit now terminates its FPM worker or Apache child
(the master / Apache parent spawns a new one).
The Fatal error: Allowed memory size ... exhausted message is written to the worker's stderr (it shows up in the
FPM or Apache error log) instead of going through the PHP error handlers, and the client gets a dropped connection
(a 502 behind a proxy) instead of a 500.
docker pull registry.nimahosts.com/nimasystems-public/php-fpm:7.3-prod
docker pull registry.nimahosts.com/nimasystems-public/php-fpm:7.4-prod
docker pull registry.nimahosts.com/nimasystems-public/php-fpm:8.2-prod
docker pull registry.nimahosts.com/nimasystems-public/php:7.3-apache # replaces FROM php:7.3-apacheEach is a drop-in replacement for the matching upstream image: the upstream image (pinned by digest) is
kept as is, only the PHP binaries, headers and bundled shared modules (opcache, sodium) are replaced, and
/usr/src/php.tar.xz holds the patched sources (8.2: the 8.2.35 release) so docker-php-ext-install builds
against them. The build fails if the fixed PHP is not active.
Limitations:
- PECL and other extensions in the upstream images were compiled against the unpatched headers and are not rebuilt. The fix itself is in the PHP core binaries; only the overflow checks that PHP's headers inline into those extensions keep the old behavior.
- 8.2: the bundled extensions that devilbox built as shared modules (gd, intl, soap, mysqli, pdo_*, zip, ...) are
still the 8.2.1 builds (
phpversion('intl')reports 8.2.1); only the core,opcacheandsodiumare 8.2.35.
.github/workflows/build.yml builds all images for linux/amd64 and
linux/arm64 on native runners, pushes to registry.nimahosts.com, sends a Slack notification per image and
creates a GitHub release.
git tag v1.3.0
git push origin v1.3.0
# -> registry.nimahosts.com/nimasystems-public/php-fpm:{7.3,7.4,8.2}-prod-1.3.0 and :{7.3,7.4,8.2}-prod
# registry.nimahosts.com/nimasystems-public/php:7.3-apache-1.3.0 and :7.3-apacheOr run the workflow manually (Actions -> build -> Run workflow) with a version.
Required repository secrets: REGISTRY_NIMAHOSTS_USERNAME, REGISTRY_NIMAHOSTS_PASSWORD, SLACK_WEBHOOK_URL.
Local build:
docker build -t php-fpm:7.4-prod-php2shell -f Dockerfiles/php2shell/Dockerfile-7.4 Dockerfiles/php2shellThe upstream README follows.
Available Architectures: amd64, arm64
This repository will provide you fully functional PHP-FPM Docker images in different flavours, versions and packed with different types of integrated PHP modules. It also solves the problem of syncronizing file permissions of mounted volumes between the host and the container.
ℹ️ For details see Documentation: Syncronize File Permissions
This repository also allows you to quickly generate and build your own custom PHP-FPM Docker image with whatever PHP extension your desire for whatever PHP version you want and for any platform you're on (amd64 or arm64). Jump to #Build your own image.
| PHP-FPM | Reference Implementation |
|---|---|
![]() |
![]() |
| Streamlined PHP-FPM images | The Devilbox |
docker pull devilbox/php-fpm:<tag>5.2-base,5.3-base,5.4-base,5.5-base,5.6-base,7.0-base,7.1-base,7.2-base,7.3-base,7.4-base,8.0-base,8.1-base,8.2-base5.2-mods,5.3-mods,5.4-mods,5.5-mods,5.6-mods,7.0-mods,7.1-mods,7.2-mods,7.3-mods,7.4-mods,8.0-mods,8.1-mods,8.2-mods5.2-prod,5.3-prod,5.4-prod,5.5-prod,5.6-prod,7.0-prod,7.1-prod,7.2-prod,7.3-prod,7.4-prod,8.0-prod,8.1-prod,8.2-prod5.2-slim,5.3-slim,5.4-slim,5.5-slim,5.6-slim,7.0-slim,7.1-slim,7.2-slim,7.3-slim,7.4-slim,8.0-slim,8.1-slim,8.2-slim5.2-work,5.3-work,5.4-work,5.5-work,5.6-work,7.0-work,7.1-work,7.2-work,7.3-work,7.4-work,8.0-work,8.1-work,8.2-work
ℹ️ For details see Documentation: Docker Tags
ℹ️ For details see Documentation: Supported Architectures
The following PHP versions are provided by this repository.
PHP 5.2,PHP 5.3,PHP 5.4,PHP 5.5,PHP 5.6PHP 7.0,PHP 7.1,PHP 7.2,PHP 7.3,PHP 7.4PHP 8.0,PHP 8.1,PHP 8.2
Note: Unreleased PHP versions are built from custom base images.
ℹ️ For details see Documentation: PHP Versions
ℹ️ For details see Documentation: Base Images
The provided Docker images heavily rely on inheritance to guarantee smallest possible image size. Each of them provide a working PHP-FPM server and you must decide what version works best for you. Look at the sketch below to get an overview about the two provided flavours and each of their different types.
[PHP] # Base FROM image (Official PHP-FPM image)
^ #
| #
| #
[base] # Streamlined base images with host user mapping
^ # environment variables and custom configs.
| #
| #
[mods] # Installs additional PHP modules
^ # via pecl, git and other means
| #
| #
[prod] # Devilbox flavour for production
^ # (locales, postifx, socat and injectables)
| # (custom *.ini files)
| #
[slim] # Devilbox flavour with only required
^ # cli tools to have a functional intranet.
| #
| #
[work] # Devilbox flavour for local development
# (includes backup and development tools)
# (sudo, custom bash and tool configs)ℹ️ For details see Documentation: Flavours
ℹ️ For details see Documentation: Base Images
Click below listed extensions for details:
amqp
apc
apcu
bcmath
blackfire
bz2
calendar
ctype
curl
date
dba
dom
enchant
ereg
exif
FFI
fileinfo
filter
ftp
gd
gettext
gmp
hash
iconv
igbinary
imagick
imap
interbase
intl
ioncube
json
ldap
libxml
lz4
lzf
mbstring
mcrypt
memcache
memcached
mhash
mongo
mongodb
msgpack
mysql
mysqli
mysqlnd
OAuth
oci8
OPcache
openssl
pcntl
pcre
PDO
pdo_dblib
PDO_Firebird
pdo_mysql
PDO_OCI
pdo_pgsql
pdo_sqlite
pdo_sqlsrv
pgsql
phalcon
Phar
posix
pspell
psr
random
rdkafka
readline
recode
redis
Reflection
session
shmop
SimpleXML
snmp
soap
sockets
sodium
solr
SPL
sqlite
sqlite3
sqlsrv
ssh2
swoole
sysvmsg
sysvsem
sysvshm
tidy
tokenizer
uploadprogress
uuid
vips
wddx
Xdebug
xhprof
xlswriter
xml
xmlreader
xmlrpc
xmlwriter
xsl
yaml
zip
zlib
zstd
ℹ️ For details see Documentation: PHP Modules
ℹ️ For details see Contributor Documentation: PHP Module definition
The provided Docker images offer environment variables to alter their startup behaviour.
ℹ️ For details see Documentation: Environment Variables or click on the variable name directly.
| Variable | Short description |
|---|---|
DEBUG_ENTRYPOINT |
Control docker log verbosity |
NEW_UID |
Syncronize user-id file system permissions |
NEW_GID |
Syncronize group-id file system permissions |
TIMEZONE |
Set timezone |
DOCKER_LOGS |
Make PHP log to file or docker logs |
ENABLE_MODULES |
Enable specific PHP extensions |
DISABLE_MODULES |
Disable specific PHP extensions |
ENABLE_MAIL |
Control email-catch all (to not accidentally send out emails) |
FORWARD_PORTS_TO_LOCALHOST |
Make remote ports available locally inside the container |
MYSQL_BACKUP_USER |
Set MySQL username (for backups) |
MYSQL_BACKUP_PASS |
Set MySQL password (for backups) |
MYSQL_BACKUP_HOST |
Set MySQL hostname (for backups) |
The provided Docker images offer different volumes to be mounted.
ℹ️ For details see Documentation: Volumes or click on the volume name directly.
| Volume | Short description |
|---|---|
/etc/php-custom.d/ |
Add custom PHP *.ini files |
/etc/php-fpm-custom.d/ |
Add custom PHP-FPM *.conf files |
/startup.1.d/ |
Add custom startup *.sh files |
/startup.2.d/ |
Add custom startup *.sh files |
/var/log/php/ |
Find PHP log files |
/var/mail/ |
Find sent emails |
/etc/supervisor/custom.d/ |
Add custom supervisord *.conf files |
/etc/bashrc-devilbox.d/ |
Add custom bashrc files |
/shared/backups/ |
Find MySQL backups |
/ca/ |
Add custom Certificate Authority |
Have a look at the following table to see all offered exposed ports for each Docker image flavour.
| Flavour | Port | Description |
|---|---|---|
| base mods prod slim work |
9000 |
PHP-FPM listening port |
Each PHP version is using the same sane default php.ini values, making it pain-free to switch versions and not having to worry about different php.ini settings. Note: Flavours alway inherit the settings from its parent flavour if they have no own configuration.
| Flavour | Applied php.ini files |
|---|---|
| base | php.ini and php-fpm.conf |
| mods | inherits from base |
| prod | inherits from base |
| slim | php.ini and php-fpm.conf |
| work | inherits from slim |
If you plan to use the PHP-FPM image for development, hence being able to execute common commands inside the container itself, you should go with the work Image.
The work Docker image has many common tools already installed which on one hand increases its image size, but on the other hand removes the necessity to install those tools locally.
You want to use tools such as angular-cli, codeception, composer, deployer, eslint, git, grunt-cli, gulp, laravel-installer, node, npm, nvm, phalcon-devtools, phpcs, phpunit, pm2, symfony-cli, tig, vue, webpack-cli, wp-cli, yarn, yq, zsh as well as many others, simply do it directly inside the container. As all Docker images are auto-built every night by GitHub Actions it is assured that you are always at the latest version of your favorite dev tool.
ℹ️ For details see Documentation: Available Tools
Apart from the provided tools, you will also be able to use the container similar as you would do with your host system. Just a few things to mention here:
- Mount custom bash configuration files so your config persists between restarts
- Use password-less
sudoto become root and do whatever you need to do
docker run -d -it \
-p 127.0.0.1:9000:9000 \
devilbox/php-fpm:7.2-proddocker run -d -it \
-p 127.0.0.1:9000:9000 \
-e TIMEZONE=Europe/Berlin \
devilbox/php-fpm:7.2-prodconfig/ is a local directory that will hold the PHP *.ini files you want to load into the Docker container.
# Create config directory to be mounted with dummy configuration
mkdir config
# Xdebug 2
echo "xdebug.enable = 1" > config/xdebug.ini
# Xdebug 3
echo "xdebug.mode = debug" > config/xdebug.ini
# Run container and mount it
docker run -d -it \
-p 127.0.0.1:9000:9000 \
-v config:/etc/php-custom.d \
devilbox/php-fpm:7.2-prodForward MySQL Port from 172.168.0.30 (or any other IP address/hostname) and Port 3306 to the PHP docker on 127.0.0.1:3306. By this, your PHP files inside the docker can use 127.0.0.1 to connect to a MySQL database.
docker run -d -it \
-p 127.0.0.1:9000:9000 \
-e FORWARD_PORTS_TO_LOCALHOST='3306:172.168.0.30:3306' \
devilbox/php-fpm:7.2-prodForward MySQL Port from 172.168.0.30:3306 and Redis port from redis:6379 to the PHP docker on 127.0.0.1:3306 and 127.0.0.1:6379. By this, your PHP files inside the docker can use 127.0.0.1 to connect to a MySQL or Redis database.
docker run -d -it \
-p 127.0.0.1:9000:9000 \
-e FORWARD_PORTS_TO_LOCALHOST='3306:172.168.0.30:3306, 6379:redis:6379' \
devilbox/php-fpm:7.2-prodOnce you set $ENABLE_MAIL=2, all mails sent via any of your PHP applications no matter to which domain, are catched locally into the devilbox account. You can also mount the mail directory locally to hook in with mutt and read those mails.
docker run -d -it \
-p 127.0.0.1:9000:9000 \
-v /tmp/mail:/var/mail \
-e ENABLE_MAIL=2 \
devilbox/php-fpm:7.2-prod~/my-host-www will be the directory that serves the php files (your document root). Make sure to mount it into both, php and the webserver.
# Start PHP-FPM container
docker run -d -it \
-v ~/my-host-www:/var/www/default/htdocs \
--name php \
devilbox/php-fpm:7.2-prod
# Start webserver and link with PHP-FPM
docker run -d -it \
-p 80:80 \
-v ~/my-host-www:/var/www/default/htdocs \
-e PHP_FPM_ENABLE=1 \
-e PHP_FPM_SERVER_ADDR=php \
-e PHP_FPM_SERVER_PORT=9000 \
--link php \
devilbox/nginx-mainlineNote: This will only work with work Docker images.
The MySQL server could be another Docker container linked to the PHP-FPM container. Let's assume the PHP-FPM container is able to access the MySQL container by the hostname mysql.
# Start container
docker run -d -it \
-e MYSQL_BACKUP_USER=root \
-e MYSQL_BACKUP_PASS=somepass \
-e MYSQL_BACKUP_HOST=mysql \
-v ~/backups:/shared/backups \
--name php \
devilbox/php-fpm:7.2-work
# Run database dump
docker exec -it php mysqldump-secure
If you want a fully functional Docker Compose setup, which allows to switch PHP versions easily, comes with web servers, database servers and much more, then head over to the Devilbox rerefence implementation :
| Reference Implementation |
|---|
![]() |
Docker images are built and tested every night by GitHub Actions and pushed to Docker hub on success. This is all done automatically to ensure that sources as well as base images are always fresh and in case of security updates always have the latest patches.
You are not interested in the provided Docker images and want to (ab)use this repository purely to generate your own custom images? You can do so with three easy commands:
# Generate Dockerfiles with only the following PHP extensions present
make gen-dockerfiles MODS="msgpack memcached pdo_mysql rdkafka"
# Pull base image for PHP 8.1 (if you don't have it locally already)
make docker-pull-base-image STAGE=mods VERSION=8.1 ARCH=linux/arm64
# Build PHP 8.1 for arm64 with above specified extensions
make build STAGE=mods VERSION=8.1 ARCH=linux/arm64ℹ️ For details see Abuser Documentation: Build your own image
Contributors are welcome. Feel free to star and clone this repository and submit issues and pull-requests. Add examples and show what you have created with the provided images. If you see any errors or ways to improve this repository in any way, please do so.
ℹ️ For details see Contributor Documentation: PHP Module definitions
ℹ️ For details see Contributor Documentation: PHP Tools definitions
If you want to add custom modules, tools or apply any other changes, but don't think it fits in here, you can do so over at the PHP-FPM Community Images.
See the reference implementation below:
| Project | Author | build | Architecture | Docker Tag |
|---|---|---|---|---|
| 📁 devilbox/ | 💻 amd64 💻 arm64 |
<V>-devilbox |
ℹ️
<V>in the Docker tag above stands for the PHP version. E.g.:5.4or8.1, etc
Show some love for the following sister projects.
In case you seek help, go and visit the community pages.
|
|
|
|
| devilbox.readthedocs.io | discord/devilbox | devilbox.discourse.group |
Thanks for contributing 🖤
I try to keep up with literally over 100 projects besides a full-time job. If my work is making your life easier, consider contributing. 🖤
Findme: 🐱 cytopia / devilbox | 🐋 cytopia / devilbox | 🐦 everythingcli / devilbox | 📖 everythingcli.org
Contrib: PyPI: cytopia · Terraform: cytopia · Ansible: cytopia
Copyright (c) 2017 cytopia



