Sign inSign up

madlabcg/laravel-php

By madlabcg

•Updated 20 days ago

PHP-FPM + nginx + supervisor runtime for Laravel apps. Multi-arch (amd64/arm64). No app code.

Image
Languages & frameworks
Web servers
0

1.5K

madlabcg/laravel-php repository overview

⁠laravel-php

Production runtime for Laravel applications: PHP-FPM + nginx + supervisor on Alpine Linux, ready to run the web server, queue workers and the scheduler from a single container.

The image contains no application code and no secrets. Your app's Dockerfile starts FROM it and only adds dependencies, compiled assets and source code, so builds take seconds instead of minutes.

  • Platforms: linux/amd64, linux/arm64
  • Listens on port 8080
  • App directory: /var/www/html (docroot /var/www/html/public)

⁠Tags

Tags follow <exact runtime version>-r<revision>:

TagExampleMoves?Use it for
<php>-r<n>8.4.26-r1Never (immutable)Production — reproducible builds
<php>8.4.26To the latest revision of that PHP versionInspection
<line>8.4To the latest build of the PHP lineEnvironments that want patches automatically
latest—To the latest build of the newest PHP lineQuick tests only

The revision (-r1, -r2, …) increases when the image is rebuilt without a PHP change (Alpine security patches, a new extension, config changes) and resets to -r1 with every new PHP release.

⁠PHP lines

One line per PHP version, all with the same contents. Pick the one your app needs.

LineImmutable tagNotes
8.58.5.11-r1Newest line: latest points here
8.48.4.26-r1
8.28.2.34-r1
7.47.4.33-r1Legacy: PHP 7.4 and Alpine 3.16 are end of life, with no PHP security fixes. Ships nginx 1.22. Use it only for apps that cannot move to PHP 8 yet

⁠What's inside

ComponentDetails
PHPOfficial php:<version>-fpm-alpine, FPM on 127.0.0.1:9000
Extensionsbcmath, exif, gd, intl, mbstring, opcache, pcntl, pdo_mysql, pdo_pgsql, redis, zip, plus the core ones (pdo_sqlite, curl, openssl, sodium, xml, …)
ToolsComposer 2, install-php-extensions, bash, curl, zip/unzip, postgresql-client
nginxPort 8080, Laravel front controller, /health answered by nginx, dotfiles and project metadata denied
supervisorphp-fpm, nginx, N × queue:work, schedule:work, plus any /etc/supervisor/conf.d/*.conf
PHP config/usr/local/etc/php/conf.d/zz-madlab.ini: 1 GB memory, 100 MB uploads, OPcache without timestamp validation, UTC, errors to stderr
Entrypoint/usr/local/bin/madlab-entrypoint
Healthcheck/usr/local/bin/madlab-healthcheck

Not included: Node.js, git and compilers. Build your frontend assets in a separate stage.

⁠Quick start

# syntax=docker/dockerfile:1
ARG BASE_IMAGE=madlabcg/laravel-php:8.4.26-r1

# PHP dependencies
FROM ${BASE_IMAGE} AS vendor
COPY composer.json composer.lock ./
RUN composer install --no-interaction --no-scripts --no-autoloader --prefer-dist

# Frontend assets (architecture independent, always built natively)
FROM --platform=$BUILDPLATFORM node:22-alpine AS assets
WORKDIR /var/www/html
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
COPY --from=vendor /var/www/html/vendor ./vendor
RUN npm run build

# Application
FROM ${BASE_IMAGE}
ARG GIT_COMMIT=unknown
COPY --from=vendor --chown=www-data:www-data /var/www/html/vendor ./vendor
COPY --chown=www-data:www-data . .
COPY --from=assets --chown=www-data:www-data /var/www/html/public/build ./public/build
RUN composer dump-autoload --optimize --classmap-authoritative \
    && echo "${GIT_COMMIT}" > /.git-commit \
    && date -u +%Y%m%d-%H%M%S > /.build-date

Add a .dockerignore that excludes at least .git, .env*, node_modules, vendor, public/build and storage/* runtime files.

Run it:

docker run -d -p 8080:8080 \
  -e APP_KEY=base64:... \
  -e DB_CONNECTION=pgsql -e DB_HOST=db -e DB_DATABASE=app -e DB_USERNAME=app -e DB_PASSWORD=secret \
  -e RUN_MIGRATIONS=true -e FORCE_MIGRATIONS=true \
  my-laravel-app

⁠Startup sequence

On every container start madlab-entrypoint:

  1. Waits for the database (a server that answers "database does not exist" counts as ready).
  2. Creates the storage/ and bootstrap/cache directories, clears compiled views and fixes permissions for www-data.
  3. Requires APP_KEY, runs storage:link and checks public/build/manifest.json.
  4. Runs a fresh install or migrations when requested.
  5. Runs php artisan optimize when APP_ENV=production.
  6. Runs every /docker-entrypoint-init.d/*.sh in alphabetical order.
  7. Starts the CMD (supervisor by default).

⁠Environment variables

VariableDefaultDescription
APP_KEY—Required
APP_ENVproductionEmpty counts as production, which keeps destructive steps disabled
DB_CONNECTIONpgsqlpgsql, mysql, mariadb or sqlite for the readiness check; other drivers are assumed ready
WAIT_FOR_DBtruefalse checks the database only once
DB_WAIT_TIMEOUT60Seconds to wait for the database
SKIP_DB_ON_FAILfalseStart even if the database is unreachable (skips migrations)
RUN_MIGRATIONS—true runs migrate --force on start
FORCE_MIGRATIONS—Also required in production, on top of RUN_MIGRATIONS
FRESH_INSTALL / FORCE_FRESH_INSTALL—Missing or empty database: migrate and seed. Migrated database: migrate:fresh --seed, never in production, once per container
REQUIRE_VITE_MANIFESTtrueSet false for apps without Vite
QUEUE_WORKER_ENABLEtrueRun queue workers under supervisor
QUEUE_WORKER_PROCS4Number of workers
QUEUE_WORKER_CONNECTION$QUEUE_CONNECTION or databaseQueue connection
QUEUE_WORKER_QUEUEdefaultQueues to listen on, e.g. high,default
QUEUE_WORKER_SLEEP / _TRIES / _MAX_TIME / _MEMORY3 / 3 / 3600 / 512queue:work options
SCHEDULER_ENABLEtrueRun schedule:work
SENTRY_RELEASEcommit or build-<date>Taken from /.git-commit or /.build-date when unset. An empty commit (a GIT_COMMIT build arg without a value) counts as unknown and falls back to the build date
CHECK_DBfalseThe healthcheck also tests the database connection
HEALTHCHECK_PATH/Path requested by the healthcheck (must answer below 500)

Boolean flags accept true, 1 or yes, tolerating quotes, spaces and inline # comments.

⁠Customizing

NeedIn your Dockerfile
Another PHP extensionRUN install-php-extensions imagick
A system packageRUN apk add --no-cache ghostscript
PHP settingsCOPY php.ini /usr/local/etc/php/conf.d/zzz-app.ini
A custom nginx vhostCOPY nginx.conf /etc/nginx/http.d/default.conf
Extra processes (Horizon, Reverb…)COPY horizon.conf /etc/supervisor/conf.d/horizon.conf (set QUEUE_WORKER_ENABLE=false if it replaces the workers)
Startup hooksCOPY docker/init/ /docker-entrypoint-init.d/

⁠Healthcheck

The image defines a HEALTHCHECK that verifies php-fpm and nginx are running and that the app answers below HTTP 500. In Compose:

healthcheck:
  test: ["CMD", "/usr/local/bin/madlab-healthcheck"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 90s

Tag summary

Content type

Image

Digest

sha256:9217939a3…

Size

84.6 MB

Last updated

20 days ago

docker pull madlabcg/laravel-php