Opinionated, production-ready Docker images for PHP on Debian. Each image bundles PHP-FPM + Nginx + Supervisor + Composer + ionCube + Redis + supercronic in a single container, ready to drop a PHP application into /var/www/html.
Images are built from the official php:<version>-fpm-* bases and published to GitHub Container Registry.
Built and published from .github/workflows/ci.yml on every push to main.
| Tag | Base image |
|---|---|
7.4-fpm |
php:7.4-fpm-bullseye |
8.1-fpm |
php:8.1-fpm-bookworm |
8.2-fpm |
php:8.2-fpm-bookworm |
8.3-fpm |
php:8.3-fpm-bookworm |
8.4-fpm |
php:8.4-fpm-bookworm |
8.5-fpm |
php:8.5-fpm-bookworm |
Pull from GHCR:
docker pull ghcr.io/itsmattius/php-debian:8.3-fpm- Web stack — Nginx (default site at
.docker/etc/nginx/sites-available/default) talking to PHP-FPM over a Unix socket at/run/php/php-fpm.sock. - PHP extensions —
bcmath,opcache,mysqli,pdo_mysql,gmp,intl,zip,sockets,bz2,pcntl,soap,gd, plusredis(PECL) and the ionCube Loader. - Composer — installed globally; project-local
vendor/binis onPATH. - Process supervision —
supervisordrunsphp-fpm,nginx, and a cron worker. See.docker/etc/supervisor/conf.d/master.conf. - Cron — supercronic reads
/etc/crontab. Default jobs run/var/www/html/crons/cron.phpand/var/www/html/crons/pop.phpevery 5 minutes — override/etc/crontabif your app uses different paths. - Logs — Nginx access/error and supervisor/PHP-FPM output are wired to
stdout/stderrsodocker logsjust works.
Mount your app at /var/www/html and expose port 80:
docker run -d \
--name myapp \
-p 8080:80 \
-v "$PWD":/var/www/html \
ghcr.io/itsmattius/php-debian:8.3-fpmOr with compose.yaml:
services:
app:
image: ghcr.io/itsmattius/php-debian:8.3-fpm
ports:
- "8080:80"
volumes:
- ./:/var/www/htmlThe Nginx site serves from /var/www/html with index.php as the front controller (try_files $uri $uri/ /index.php?$query_string), so frameworks like Laravel or Symfony work out of the box. client_max_body_size is 0 (unlimited) and fastcgi_read_timeout is 900s.
pm = ondemand, pm.max_children = 100, pm.max_requests = 500, open_basedir restricted to /var/www/, /tmp/, /var/tmp/, /dev/urandom. Edit .docker/usr/local/etc/php-fpm.d/www.conf and rebuild to change.
The Nginx config maps X-Forwarded-Proto: https into the HTTPS FastCGI param, so PHP sees the correct scheme when running behind a TLS-terminating reverse proxy.
All baked-in config lives under .docker/ and is copied into the image during build:
.docker/etc/nginx/sites-available/default— Nginx vhost.docker/etc/supervisor/conf.d/master.conf— supervisord programs.docker/usr/local/etc/php/php.ini— base php.ini.docker/usr/local/etc/php/conf.d/opcache.ini— OPcache settings.docker/usr/local/etc/php-fpm.d/www.conf— FPM pool.docker/usr/local/etc/php-fpm.d/zz-docker.conf— FPM docker overrides
To build locally:
docker build -f 8.3-fpm.Dockerfile -t php-debian:8.3-fpm .The Dockerfiles use a BuildKit bind mount (--mount=type=bind,source=.docker,...), so BuildKit must be enabled (default on modern Docker).
MIT © Mehdi Abedi