Sign inSign up

practicalwebuser/mod_apex-apache

By practicalwebuser

•Updated 3 days ago

PHP 8.4 ZTS (thread-safe) Apache Docker image with event MPM, mod_apex and OPcache; no PHP-FPM

Image
0

1.1K

practicalwebuser/mod_apex-apache repository overview

⁠PHP 8.4 ZTS Apache Docker image with event MPM | PHP Apex

Docker Hub repository⁠

PHP 8.4 ZTS (thread-safe) Apache Docker image with event MPM, mod_apex and OPcache; no PHP-FPM.

One container. One request path. PHP ready inside Apache.

practicalwebuser/mod_apex-apache:php8.4 puts Apache, PHP 8.4.27 ZTS, and PHP Apex in one ready-to-run image. PHP executes directly in Apache's worker threads, so you avoid a separate PHP-FPM container, FastCGI socket, and second request queue.

Run modern PHP applications with one web service and no separate PHP-FPM process pool. Keep Apache's event MPM without going back to legacy prefork mod_php.

The image automatically sizes its worker pool from the container's effective CPU and memory limits. A 2-CPU, 2-GiB container selects four workers, disables keep-alive, and keeps its first Apache child persistent.

⁠Everything included

The image is ready with the web server, PHP runtime, module wiring, and common extensions already together:

  • Apache 2.4 using the event MPM
  • PHP 8.4.27 ZTS with the embed SAPI
  • PHP Apex (mod_apex) enabled for .php files
  • OPcache with JIT support and APCu
  • Redis for application caching and sessions
  • MySQL support through mysqli and PDO MySQL
  • SQLite through PDO SQLite
  • Imagick and GD with JPEG, PNG, WebP, and FreeType support
  • curl, mbstring, intl, fileinfo, EXIF, BCMath, GMP, sodium, SOAP, XML, SimpleXML, XMLReader, XMLWriter, XSL, and ZIP
  • resource-aware Apache worker sizing with keep-alive disabled
  • hardened Apache defaults, container-friendly logs, and /healthz

The runtime uses Debian 13 (Trixie) Slim. Compilers and build tools are not kept in the published runtime image.

⁠Start your PHP app

mkdir -p "$(pwd)/app"
test -e "$(pwd)/app/healthz" || printf 'ok\n' > "$(pwd)/app/healthz"
docker pull practicalwebuser/mod_apex-apache:php8.4
docker run -d --name my-php-app \
  --cpus=2 --memory=2g \
  -p 8080:80 \
  -v "$(pwd)/app:/var/www/html:ro" \
  practicalwebuser/mod_apex-apache:php8.4

Open http://your-server:8080. Your application belongs in ./app.

The example mounts application code read-only. If your application writes uploads, cache files, or generated content, mount only those directories as separate writable volumes.

A bind mount on /var/www/html hides the image's bundled static /healthz, so the example creates a replacement in the mounted application. Keep that file in the deployed document root, or bake the application into a derived image; otherwise Docker reports the container as unhealthy when its health check gets a 404 response.

⁠Why PHP Apex

  • One container, one request path. Apache receives the request and runs PHP in the same worker. No PHP-FPM service to deploy, monitor, or tune.
  • Built for Apache event MPM. Keep Apache's modern threaded request model while PHP uses its thread-safe ZTS runtime.
  • PHP stays ready. Each Apache worker keeps its PHP runtime available for the next request instead of handing work across a FastCGI boundary.
  • Bring popular PHP applications. The image includes OPcache, APCu, Redis, Imagick, curl, mbstring, intl, GD, PDO/MySQL, SQLite, zip, sodium, GMP, SOAP, XSL, and more.
  • Container-friendly by default. The image detects cgroup CPU and memory limits, sends logs to docker logs, and includes /healthz.

⁠Run it confidently

Set CPU and memory limits with your container platform. PHP Apex uses two workers per effective CPU, capped by a conservative memory budget. Keep-alive remains disabled unless explicitly enabled. For a 2-CPU, 2-GiB container, start with:

docker run -d --name my-php-app \
  --cpus=2 --memory=2g \
  -p 8080:80 \
  practicalwebuser/mod_apex-apache:php8.4

Important: do not manually override Apache's ServerLimit, ThreadLimit, ThreadsPerChild, or MaxRequestWorkers directives. The PHP Apex entrypoint automatically generates these settings as one valid layout from the available CPU and memory. Changing only one directive can make Apache silently run a different number of workers, increasing memory use or reducing performance. Use the documented APEX_* environment variables only when a measured deployment requires an override.

For a measured high-traffic deployment, enable keep-alive and set a worker limit from 1 to 512:

docker run -d --name my-php-app \
  --cpus=2 --memory=2g \
  -e APEX_KEEP_ALIVE=1 \
  -e APEX_MAX_REQUEST_WORKERS=8 \
  -p 8080:80 \
  -v "$(pwd)/app:/var/www/html:ro" \
  practicalwebuser/mod_apex-apache:php8.4

Let automatic sizing establish the baseline. Enable APEX_KEEP_ALIVE=1 and override the worker limit only for a measured high-traffic deployment. APEX_KEEP_ALIVE accepts only 0 or 1. The entrypoint always generates a valid event-MPM layout; if a worker override cannot be represented exactly within its eight-child, 64-thread envelope, it logs the small safe downward adjustment.

The default APEX_MAX_CONNECTIONS_PER_CHILD=0 keeps the single baseline child persistent. Multi-child deployments can test 1000 or 10000 to enable count-based recycling; measure memory, restarts, and latency before changing it.

⁠Writable plugins, themes, or templates

OPcache is optimized for immutable containers by default. If PHP code can change while the container is running, enable timestamp validation so those changes are loaded:

docker run -d --name my-php-app \
  -e APEX_OPCACHE_VALIDATE=1 \
  -p 8080:80 \
  -v "$(pwd)/app:/var/www/html" \
  practicalwebuser/mod_apex-apache:php8.4

Keep the default APEX_OPCACHE_VALIDATE=0 for code baked into the image or mounted read-only. Set it to 1 for writable PHP code, including volume-mounted WordPress plugins and themes. Only 0 and 1 are accepted.

⁠Security controls for a PaaS

PHP version headers are disabled, and session cookies default to HttpOnly with SameSite=Lax. Applications can override their own cookie policy.

If customers can upload PHP code, opt into tighter process and URL access:

docker run -d --name my-php-app \
  -e APEX_DISABLE_FUNCTIONS=exec,passthru,shell_exec,system,proc_open,popen \
  -e APEX_ALLOW_URL_FOPEN=0 \
  -p 8080:80 \
  practicalwebuser/mod_apex-apache:php8.4

The disabled-function list is empty by default because some applications use proc_open. APEX_ALLOW_URL_FOPEN defaults to 1. It and the other Boolean image settings accept only 0 or 1.

⁠Real visitor IPs behind a proxy

The image includes mod_remoteip but trusts no network automatically. For a Traefik network such as 10.89.0.0/16, set:

-e APEX_TRUSTED_PROXY="10.89.0.0/16"

Space-separate multiple trusted CIDRs. In a Cloudflare → Traefik deployment, Traefik must validate and sanitize Cloudflare's forwarded headers, or PHP Apex must also receive the current Cloudflare proxy ranges. Do not use 0.0.0.0/0. Confirm $_SERVER['REMOTE_ADDR'] before using it for security decisions.

The default virtual host uses AllowOverride All, so applications can use standard Apache .htaccess directives, including rewrites. mod_apex does not register php_value or php_admin_value; use a mounted PHP INI file for PHP settings.

Check availability without invoking PHP:

curl -fsS http://127.0.0.1:8080/healthz
docker logs my-php-app

/healthz is a small static check for container and load-balancer monitoring. The image does not publish /test.php by default. You can temporarily set APEX_ENABLE_TEST_PAGE=1 for a private PHP smoke test. That option overwrites /var/www/html/test.php, requires a writable document root, and is not compatible with the read-only bind mount above. On a writable host mount, the file persists after the container stops; delete it and remove the setting before public exposure.

The image serves HTTP on port 80. Put TLS certificates and public internet traffic at your reverse proxy or load balancer.

⁠Image tag

TagUse
php8.4Current PHP 8.4.27 ZTS, Apache, and PHP Apex v0.1.10

The tag is updated in place. Its current digest is sha256:e9ef0395e468139755143f0a0a1052b915b05e33aea3164520e5697423aeed69. For repeatable production deployments, pull and test the tag, then pin its digest in your deployment configuration.

⁠Need more setup detail?

See the Docker guide⁠ for writable application directories, custom Apache/PHP settings, proxy setup, and upgrade guidance.

⁠License

PHP Apex is released under the Apache License 2.0⁠. PHP, Apache HTTP Server, and bundled extensions retain their respective licenses.

Tag summary

Content type

Image

Digest

sha256:c7317680e…

Size

129.9 MB

Last updated

3 days ago

docker pull practicalwebuser/mod_apex-apache:php8.4