PHP-FPM + Nginx + Supervisor images for Laravel on Alpine and Debian, with optional build toolchain
8.0K
Lightweight, production-ready PHP images for running Laravel (and other PHP applications) behind Nginx,
in a single container. Alpine images are built on the official php:*-fpm-alpine images; the Debian
(trixie) variant compiles PHP from source on debian:trixie-slim.
Source and docs: https://github.com/tgivslife/laravel-alpine
| Component | Role |
|---|---|
| PHP-FPM | Runs the application, with common extensions preinstalled |
| Nginx | Serves the application from /var/www/html/public on port 80 and passes PHP to PHP-FPM |
| Supervisor | Starts and manages nginx, php-fpm, the Laravel scheduler (on by default) and Horizon (opt-in) |
PHP extensions include bcmath, curl, exif, gd, intl, mbstring, mysqli, pdo_mysql,
pdo_pgsql, pdo_sqlite, pgsql, pcntl, redis, sockets, sodium, zip and Zend OPcache.
Run php -m inside a container for the full list of a given tag.
Every runtime tag has a matching -build tag that adds a build toolchain:
Composer, Node.js, npm and Git. Use -build to install dependencies and compile assets, and the
slim runtime tag to run the result.
Tag format:
<php version>-laravel-alpine<alpine version>[-build]<php version>-laravel-<debian codename>[-build]Latest per PHP version:
| PHP | Alpine | Debian |
|---|---|---|
| 8.5 | 8.5.11-laravel-alpine3.24, 8.5.11-laravel-alpine3.24-build | 8.5.10-laravel-trixie, 8.5.10-laravel-trixie-build |
| 8.4 | 8.4.23-laravel-alpine3.24, 8.4.23-laravel-alpine3.24-build | — |
| 8.3 | 8.3.32-laravel-alpine3.24, 8.3.32-laravel-alpine3.24-build | — |
| 8.2 | 8.2.15-laravel-alpine3.18, 8.2.15-laravel-alpine3.18-build | — |
| 7.4 | 7.4.33-laravel-alpine3.16, 7.4.33-laravel-alpine3.16-build | — |
Recent tags are multi-architecture (linux/amd64, linux/arm64): docker pull picks the right one.
Older patch releases remain available on the Tags page;
the exact package versions of each 8.5 Alpine release are listed in its
GitHub release.
PHP 8.2 and 7.4 are end-of-life upstream and kept for legacy applications only. They run the scheduler through cron and take a different set of environment variables than the ones below.
ARG PHP_TAG=8.5.11-laravel-alpine3.24
FROM stsdockerhub/php:${PHP_TAG}-build AS build
WORKDIR /var/www/html
COPY . .
RUN composer install --no-dev --optimize-autoloader \
&& npm ci \
&& npm run build \
&& tar --owner=www-data --group=www-data \
--exclude=.git --exclude=docker --exclude=node_modules -czf /tmp/app.tar.gz .
FROM stsdockerhub/php:${PHP_TAG}
WORKDIR /var/www/html
COPY --from=build /tmp/app.tar.gz .
RUN tar -xf app.tar.gz && rm app.tar.gz
# Optional: startup hooks (migrations, cache warm-up, …)
COPY docker/docker-entrypoint.d /docker-entrypoint.d/
RUN chmod +x /docker-entrypoint.d/*
docker build -t my-laravel-app .
docker run -p 8080:80 --env-file .env my-laravel-app
The application is then served at http://localhost:8080/.
A complete sample application (Laravel + Vue starter kit, with scheduler and Horizon test jobs) is in
example-app.
For PHP 8.3 and newer. All optional; defaults shown.
OS
| Variable | Default | Description |
|---|---|---|
TZ | Europe/Bucharest | Container timezone |
Laravel
| Variable | Default | Description |
|---|---|---|
LARAVEL_SCHEDULER_ENABLE | 1 | Run php artisan schedule:work under Supervisor (output goes to container logs) |
LARAVEL_HORIZON_ENABLE | 0 | Run Laravel Horizon for Redis queues under Supervisor |
PHP
| Variable | Default | Description |
|---|---|---|
PHP_MAX_EXECUTION_TIME | 60 | Seconds |
PHP_MEMORY_LIMIT | 128M | On PHP 8.5, ini_set('memory_limit', …) can still raise it at runtime |
PHP_UPLOAD_MAX_FILESIZE | 50M | |
PHP_POST_MAX_SIZE | 50M | 0 disables the limit |
OPcache
| Variable | Default |
|---|---|
PHP_OPCACHE_ENABLE | 1 |
PHP_OPCACHE_ENABLE_CLI | 1 |
PHP_OPCACHE_MEMORY_CONSUMPTION | 512 |
PHP_OPCACHE_INTERNED_STRINGS_BUFFER | 128 |
PHP_OPCACHE_MAX_ACCELERATED_FILES | 65406 |
PHP_OPCACHE_MAX_WASTED_PERCENTAGE | 15 |
PHP_OPCACHE_VALIDATE_TIMESTAMPS | 0 |
PHP_OPCACHE_SAVE_COMMENTS | 1 |
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0is tuned for immutable production images: code changes are not picked up until the container restarts. Set it to1for development with mounted source code.
PHP-FPM
| Variable | Default |
|---|---|
PHP_FPM_PM_MAX_CHILDREN | 50 |
PHP_FPM_PM_START_SERVERS | 20 |
PHP_FPM_PM_MIN_SPARE_SERVER | 10 |
PHP_FPM_PM_MAX_SPARE_SERVERS | 30 |
Nginx
| Variable | Default | Description |
|---|---|---|
NGINX_FASTCGI_READ_TIMEOUT | 60s | Timeout between reads from PHP-FPM |
NGINX_CLIENT_MAX_BODY_SIZE | 50m | Max request body (keep in line with PHP_POST_MAX_SIZE) |
NGINX_SET_REAL_IP_FROM | 127.0.0.1 | Trusted proxy address(es) for the real client IP |
NGINX_WORKER_CONNECTIONS | 4096 | Connections per worker |
NGINX_WORKER_RLIMIT_NOFILE | 65535 | Open file limit per worker |
80 | HTTP (Nginx) |
/var/www/html | Application root; Nginx serves public/ |
/docker-entrypoint.d/ | Executable *.sh startup scripts, run in order before Supervisor starts the services; a failing script stops the container |
The images (PHP 8.3 and newer) declare a Docker HEALTHCHECK that requests /ping through Nginx to PHP-FPM
every 30 seconds, so the container turns unhealthy if either is down. /ping answers only requests from
inside the container.
Each image is labelled with its version, git commit and build date:
docker inspect -f '{{json .Config.Labels}}' stsdockerhub/php:<tag> (8.5 Alpine releases onward).
Build arguments and the full extension list of each image are in the version folders of the GitHub repository; exact package versions are in the image README (manually published images) or the GitHub release (8.5 Alpine).
Content type
Image
Digest
sha256:5108e9cc7…
Size
154.2 MB
Last updated
11 days ago
docker pull stsdockerhub/php:8.5.11-laravel-trixie-build