Go to file
Fabian @ Blax Software 96bca57bde fix(perms,mysql): auto-fix storage ownership + skip self-signed cert verify
Two recurring foot-guns in production stacks rolled into one image-level fix:

1. storage/ + bootstrap/cache/ ownership drift. ENABLE_LARAVEL_PERMS was
   opt-in (default 0) and only chmod'd the top-level dir — so any subdir
   created later by a different UID (root, nobody, …) stayed un-writable
   for www-data. Symptom: workkit:db:backup pumping a multi-GB mysqldump
   into a doomed bash redirect that fails with "Permission denied" only
   after the pipeline starts. Now default-on (=1), recursive chown +
   chmod ug+rwX, SGID on dirs so future files inherit the group, and we
   pre-create the subdirs that ship empty (incl. storage/backups/) so
   artisan never creates one as the wrong user.

2. mysql client TLS verification against self-signed in-cluster certs.
   `php artisan db` failed with "TLS/SSL error: self-signed certificate
   in certificate chain" because modern mysql/mariadb clients auto-enable
   ssl-verify-server-cert when a password is on argv. Drops a
   /etc/mysql/conf.d/00-laravel-client.cnf with ssl-verify-server-cert=OFF
   so the connection still negotiates TLS but skips the chain check —
   the right tradeoff for a private docker network. Override per-host
   with MYSQL_CLIENT_VERIFY=ON or by mounting a stricter .cnf.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:05:14 +02:00
config Initial commit: multi-version PHP+Nginx Docker image for Laravel 2026-04-15 09:57:37 +02:00
docs chore: clean up stale root files, minor doc edits 2026-04-15 10:12:08 +02:00
scripts fix(perms,mysql): auto-fix storage ownership + skip self-signed cert verify 2026-05-07 10:05:14 +02:00
.dockerignore Initial commit: multi-version PHP+Nginx Docker image for Laravel 2026-04-15 09:57:37 +02:00
Dockerfile fix(perms,mysql): auto-fix storage ownership + skip self-signed cert verify 2026-05-07 10:05:14 +02:00
README.md fix(perms,mysql): auto-fix storage ownership + skip self-signed cert verify 2026-05-07 10:05:14 +02:00
docker-bake.hcl Initial commit: multi-version PHP+Nginx Docker image for Laravel 2026-04-15 09:57:37 +02:00

README.md

Blax Software OSS

docker-laravel

A runtime environment for Laravel applications — not Laravel itself.

This image provides everything a Laravel app needs to run: PHP-FPM, Nginx, Composer, Node.js, and a curated set of PHP extensions and system tools. Mount your Laravel project at /var/www/html and you're ready to go.

Built for PHP 7.4 through 8.5, covering Laravel 9 13.

Available Tags

By PHP version

Tag PHP Suitable for Laravel
blaxsoftware/laravel:php7.4 7.4 Legacy (< 9)
blaxsoftware/laravel:php8.0 8.0 9
blaxsoftware/laravel:php8.1 8.1 9, 10
blaxsoftware/laravel:php8.2 8.2 9, 10, 11, 12
blaxsoftware/laravel:php8.3 8.3 10, 11, 12, 13
blaxsoftware/laravel:php8.4 8.4 11, 12, 13
blaxsoftware/laravel:php8.5 8.5 12, 13
blaxsoftware/laravel:latest 8.4 (alias for php8.4)
Tag Points to
blaxsoftware/laravel:laravel9 php8.1
blaxsoftware/laravel:laravel10 php8.3
blaxsoftware/laravel:laravel11 php8.4
blaxsoftware/laravel:laravel12 php8.5
blaxsoftware/laravel:laravel13 php8.5

Combo tags (specific PHP + Laravel)

blaxsoftware/laravel:laravel9-php8.0
blaxsoftware/laravel:laravel9-php8.1
blaxsoftware/laravel:laravel9-php8.2
blaxsoftware/laravel:laravel10-php8.1
blaxsoftware/laravel:laravel10-php8.2
blaxsoftware/laravel:laravel10-php8.3
blaxsoftware/laravel:laravel11-php8.2
blaxsoftware/laravel:laravel11-php8.3
blaxsoftware/laravel:laravel11-php8.4
blaxsoftware/laravel:laravel12-php8.2
blaxsoftware/laravel:laravel12-php8.3
blaxsoftware/laravel:laravel12-php8.4
blaxsoftware/laravel:laravel12-php8.5
blaxsoftware/laravel:laravel13-php8.3
blaxsoftware/laravel:laravel13-php8.4
blaxsoftware/laravel:laravel13-php8.5

Quick Start

# Build a single version
docker build --build-arg PHP_VERSION=8.4 -t docker-laravel:php8.4 .

# Build all versions
./scripts/build.sh

# Build only specific PHP versions
./scripts/build.sh 8.4 8.5

# Build all versions with buildx bake
docker buildx bake

# Build only actively-supported PHP versions
docker buildx bake active

plug-n-pray 🙏

Generate a full Docker Compose boilerplate for any Laravel project:

# From your Laravel project root — one-liner:
curl -fsSL https://raw.githubusercontent.com/blax-software/docker-laravel/main/scripts/plug-n-pray.sh | bash

# With options:
./plug-n-pray.sh --php=8.4 --name=my-app --host=my-app.localhost --horizon

# Or via artisan (requires blax-software/laravel-workkit):
php artisan workkit:plug-n-pray
php artisan workkit:plug-n-pray --php=8.5 --horizon --no-mysql

See docs/examples.md for full usage examples.

Usage in docker-compose.yml

services:
  app:
    image: docker-laravel:php8.4
    volumes:
      - ./:/var/www/html
    ports:
      - "80:80"
    environment:
      ENABLE_QUEUE: "true"
      ENABLE_SCHEDULER: "true"
      ENABLE_HORIZON: "false"
      ENABLE_LARAVEL_PERMS: "1"

Build Args

Arg Default Description
PHP_VERSION 8.4 PHP version (7.4, 8.0 8.5)
NODE_MAJOR 22 Node.js major version

Runtime Environment Variables

Variable Default Description
ENABLE_QUEUE false Start artisan queue:work via supervisor
ENABLE_SCHEDULER false Start artisan schedule:work via supervisor
ENABLE_HORIZON false Start artisan horizon via supervisor
ENABLE_LARAVEL_PERMS 1 Pre-create + chown -R www-data + chmod ug+rwX (with SGID) on storage/ and bootstrap/cache/ on every boot. Idempotent. Set to 0 to opt out.
MYSQL_CLIENT_VERIFY OFF Whether the bundled mysql/mariadb client verifies the server cert chain. Default OFF is right for in-cluster MySQL with a self-signed cert (the connection is still encrypted). Set to ON if you connect to a real public host.

What's Included

  • PHP-FPM with extensions: pdo_mysql, pdo_pgsql, mysqli, mbstring, exif, pcntl, bcmath, gd (freetype + jpeg + webp), sockets, zip, xml, soap, intl, opcache
  • PECL: redis, ev, igbinary, imagick (graceful fallback if unavailable for a PHP version)
  • OPcache with JIT auto-enabled on PHP 8.0+
  • Nginx with headers-more module, optimized for Laravel
  • Composer (latest)
  • Node.js + npm
  • Image optimizers: optipng, pngquant, gifsicle, webp, avif, svgo
  • ffmpeg, ghostscript, MySQL client

Architecture

start-container (entrypoint)
  └─ supervisord
       ├─ php-fpm          (always)
       ├─ nginx            (always)
       ├─ queue.conf       (if ENABLE_QUEUE=true)
       ├─ scheduler.conf   (if ENABLE_SCHEDULER=true)
       └─ horizon.conf     (if ENABLE_HORIZON=true)

Optional supervisor configs are generated at runtime in /etc/supervisor/laravel.d/.

Customizing Supervisor Programs

Every supervisor program lives in its own .conf file across three include directories:

Directory Purpose How to customize
/etc/supervisor/conf.d/ Core services (php-fpm, nginx) Mount a replacement file to override
/etc/supervisor/laravel.d/ Queue, scheduler, horizon (auto-generated from ENABLE_* env vars) Use env vars, or disable them and mount your own
/etc/supervisor/custom.d/ Empty — for your own programs Mount a directory or individual files

Examples:

services:
  app:
    image: blaxsoftware/laravel:php8.4
    volumes:
      - ./:/var/www/html
      # Override php-fpm config (e.g. change pool settings)
      - ./docker/php-fpm.conf:/etc/supervisor/conf.d/php-fpm.conf
      # Add custom programs (e.g. reverb, octane, custom workers)
      - ./docker/supervisor/:/etc/supervisor/custom.d/
    environment:
      ENABLE_QUEUE: "true"

To disable a core service (e.g. nginx), mount an override with autostart=false:

; my-nginx-override.conf
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=false

Star History

Star History Chart