Welcome to the Laravel-Optimized PHP Images repository! π These pre-built Docker images, hosted on the GitHub Container Registry (GHCR), are your fast track to Laravel awesomeness. Whether youβre scaffolding a new app with our Laravel installer (no local PHP needed!) or running Laravel 10, 11, or 12 with our PHP-optimized images, weβve got you covered. Packed with essential PHP extensions, running as a non-root laravel user, and optimized for production, these images make development secure, fast, and fun. Letβs build something amazing! π
Forget wrestling with PHP setups or complex Docker configs. Our images are tailor-made for Laravel developers, offering:
- Zero-Setup Scaffolding ποΈ: Create Laravel 10, 11, or 12 apps with just Docker using our installer imageβno PHP or Composer required locally.
- Top-Notch Security π: Run as the non-root
laraveluser for safer development and production. - Blazing-Fast Setup β‘: Pre-installed PHP extensions for instant local and CI/CD environments.
- Streamlined Workflows π οΈ: Focus on coding, not configuring, with Laravel-friendly defaults.
- Filament Support π¨: Dedicated images for Filament projects (see Filament-Optimized Images).
- Laravel Octane Support π: High-performance images with Swoole for Octane (see Octane-Optimized Images).
- Flexible Deployment π: Copy code into images for production speed, with minimal mounts for security.
Need imagick, pgsql, or custom tweaks? Our customization guides make it a breeze! π οΈ
Pull images from ghcr.io/redfieldchristabel/laravel and jump in! Start by creating a new app or scaffolding a Docker environment for an existing project, then run your app. Letβs go! π
Kick off your project with our laravel:installer image! This lightweight image (~120-150 MB) includes the latest Laravel CLI and scaffolds Laravel 10, 11, or 12 apps with just Dockerβno local PHP or Composer needed. Perfect for Linux, Mac, or Windows (with WSL2)!
Example:
docker run -it -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-appThis creates a Laravel 12 app (latest) in ./example-app/. The image runs laravel directly, so you just add new example-app.
Older Versions:
- Use
--versionto scaffold Laravel 10 or 11. - Example:
docker run -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-app --version=11(Laravel 11 app).
Customize Your App:
- Add stacks:
--breeze(Blade),--jet(Livewire/Inertia), or--apifor API-only apps. - Example:
docker run -v $(pwd):/app ghcr.io/redfieldchristabel/laravel:installer new example-app --breeze --version=11
Notes:
- Saves output to a volume (e.g.,
./:/app), accessible locally. - Runs as a non-root
laraveluser for security. - No PHP extensions installed, keeping it lean for scaffolding.
After scaffolding, use our PHP-based images (e.g., laravel:8.3-fpm) to run your app or scaffold a Docker environment.
For existing Laravel projects, you can use our optional bash script to set up a complete Docker environment for development and production. This script, designed to run after your Laravel project is created, generates all necessary Docker files, including docker-compose.yml for development and production, Nginx configurations, and PHP settings. It also ensures Vite is Docker-ready by setting server.host to "0.0.0.0" in vite.config.js.
Usage:
Run the script in your Laravel project directory (must contain artisan and app/):
bash -c "$(curl -fsSL https://raw.githubusercontent.com/redfieldchristabel/laravel-dockerize/main/scaffold/setup.sh)"Platform Notes:
- Linux: Run the script directly in your terminal.
- Mac: Run the script directly in Terminal or iTerm2.
- Windows: Run the script in WSL2 (Windows Subsystem for Linux 2). Install WSL2 with
wsl --installand enable Docker Desktopβs WSL2 integration. Git Bash is not recommended due to potential compatibility issues.
What the Script Does:
- Creates Docker Files: Generates
docker-compose.yml(development),build.docker-compose.yml,prod.docker-compose.yml, and Dockerfiles for PHP, Nginx, and Vite. - Configures Nginx and PHP: Adds
docker/nginx/conf/app.conf,docker/nginx/include/fpm-handler.conf, anddocker/php/file.inifor seamless integration. - Sets Up Tools: Downloads helper scripts (
art,cmpsr,pint,nd,iart) for Artisan, Composer, Node, and more. - Vite Compatibility: Modifies
vite.config.jsto setserver.hostto"0.0.0.0"(required for Docker), updating existingserverblocks or adding a new one. - Environment Setup: Copies
.env.exampleto.envif.envis missing. - Requirements: Needs
curlanddockerinstalled. Must be run in a Laravel project directory.
Using Helper Scripts: The script generates the following helper scripts in your project root to simplify running commands in Docker containers:
art: Run Artisan commands in theappcontainer (useslaravel:8.3-cli)../art migrate ./art queue:work --queue=high,default
cmpsr: Run Composer commands in theappcontainer../cmpsr install ./cmpsr require laravel/ui
pint: Run Laravel Pint (code style fixer) in theappcontainer../pint ./pint --test
nd: Run Node.js or npm commands in thevitecontainer (for Vite-based projects)../nd npm install ./nd npm run dev
iart: A shortcut for thephp artisancommand, primarily used when you are already inside the container shell (e.g., viadocker execor Portainer CLI)../iart tinker
Example Output: After running, youβll have:
docker-compose.yml: Development setup withapp,nginx,mysql,redis, and more.prod.docker-compose.yml: Production setup with minimal mounts (vendor,public).vite.config.js: Updated withserver: { host: "0.0.0.0" }for Vite in Docker.- Helper scripts (
art,cmpsr,pint,nd,iart) in the project root for easy Artisan/Composer/Node commands.
Notes:
- Run this script after creating your Laravel app (e.g., via
laravel:installer). - The generated
docker-compose.ymlmatches the Development Environment section. - Production files align with the Production Deployment section.
- The script uses images from
ghcr.io/redfieldchristabel/laravel(e.g.,laravel:8.3-fpm). - If
vite.config.jsis missing, the script skips Vite configuration.
Proceed to Running Your Laravel App to start your Dockerized environment with docker-compose up -d.
Our PHP-based images are pre-loaded with Laravelβs essential extensions and optimized for Laravel 10, 11, and 12. Use them for development, CI/CD, or production.
Supported PHP Versions:
- 8.1, 8.2, 8.3, 8.4 (latest patches via daily builds).
- Tags:
laravel:<version>(e.g.,ghcr.io/redfieldchristabel/laravel:8.3, defaults tofpm) or<version>-<variant>(e.g.,laravel:8.3-cli).
Variants:
- cli π₯οΈ: CLI PHP (Debian), great for Artisan, scripts, or cron jobs.
- fpm π: PHP-FPM (Debian), ideal for Nginx or Apache.
- cli-alpine ποΈ: CLI PHP (Alpine), lightweight.
- fpm-alpine ποΈ: PHP-FPM (Alpine), compact.
- filament π¨: CLI/FPM with Filament dependencies (e.g.,
laravel:8.3-cli-filament). - octane-swoole π: CLI with Swoole for Laravel Octane (e.g.,
laravel:8.3-cli-alpine-octane-swoole).
Example (Development):
Use the docker-compose.yml from the Development Environment section (or generated by the scaffolding script) to spin up a Laravel app with Nginx, MySQL, Redis, and more.
All images run as the non-root laravel user, reducing risks in development and production. No root privileges needed, keeping your apps secure! π
Based on Docker Hubβs official PHP images, ensuring compatibility and reliability with standard tagging conventions.
Includes Laravel 11/12βs minimum extensions:
bcmathctypefileinfojsonmbstringopensslpdopdo_mysqltokenizerxml
Add more (e.g., gd, imagick) via customization.
- fpm variants π: Port 9000 for PHP-FPM (Nginx/Apache).
- cli variants π₯οΈ: No ports, for command-line tasks.
- installer image ποΈ: No ports, for scaffolding.
- octane-swoole π: Port 8000 for Laravel Octane with Swoole.
Smart entrypoints for each image:
- cli variants π₯οΈ: Runs
php(e.g.,php artisan queue:work) via/usr/local/bin/docker-entrypoint.sh. - fpm variants π: Starts PHP-FPM via
/usr/local/bin/docker-entrypoint.sh. - installer image ποΈ: Runs
laraveldirectly (e.g.,new example-app). - octane-swoole π: Runs
php artisan octane:startvia/usr/local/bin/docker-php-entrypoint.
PHP images handle setup (permissions, composer install) and sync code in development (./:/var/www) or mount only vendor in production (./vendor:/var/www/vendor). The installer simplifies scaffolding to one command. Most apps donβt need custom entrypoints! π
Filament projects? Use -filament images with pre-installed dependencies:
ghcr.io/redfieldchristabel/laravel:8.3-cli-filamentghcr.io/redfieldchristabel/laravel:8.3-fpm-alpine-filament
For high-performance Laravel apps, use our Octane images with Swoole, the most popular and fastest server for Laravel Octane. These images include the Swoole binary pre-installed, so you donβt need to wait for a lengthy pecl install swoole. Laravel is not pre-installed; scaffold your app with the Laravel installer first.
- Available for PHP 8.1, 8.2, 8.3, 8.4.
- Tags:
laravel:<version>-cli-<variant>-octane-swoole(e.g.,laravel:8.3-cli-alpine-octane-swoole,laravel:8.3-cli-debian-octane-swoole). - Note: Currently supports only Swoole (no RoadRunner). SSL support requires extending the image (no
opensslby default for minimal size).
Example (Running Octane):
docker run -v $(pwd):/var/www -p 8000:8000 ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole- Assumes a Laravel app with Octane installed (
composer require laravel/octane) in the current directory. - Starts Octane on
http://localhost:8000.
We follow best practices for efficient containers:
- One Process Per Container β
: Separate containers for
app,queue,scheduler(no bundled Nginx/Apache). - Unified Logging π: Logs to stdout for easy
docker logsmonitoring.
Set up a dev environment with this docker-compose.yml, syncing code for real-time edits. Includes app, nginx, mysql, redis, queue, scheduler, mailpit, and phpmyadmin. This file is automatically generated by the scaffolding script.
version: '3.8'
services:
app:
image: ghcr.io/redfieldchristabel/laravel:8.3-fpm
volumes:
- .:/var/www # Sync codebase
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- mysql
- redis
env_file:
- .env
queue:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "queue:work", "--queue=high,default"]
volumes:
- .:/var/www
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env
scheduler:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "schedule:work"]
volumes:
- .:/var/www
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- .:/var/www
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ./docker/nginx/include:/etc/nginx/include
depends_on:
- app
mysql:
image: mysql:8.0
volumes:
- mysql-data:/var/lib/mysql
env_file:
- .env
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
retries: 3
timeout: 5s
redis:
image: redis:alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
retries: 3
timeout: 5s
mailpit:
image: axllent/mailpit
ports:
- "8025:8025" # Web UI
- "1025:1025" # SMTP
environment:
MP_MAX_MESSAGES: 5000
MP_SMTP_AUTH_ACCEPT_ANY: 1
MP_SMTP_AUTH_ALLOW_INSECURE: 1
phpmyadmin:
image: phpmyadmin
ports:
- "8081:80"
environment:
PMA_HOST: mysql
depends_on:
- mysql
volumes:
mysql-data:
redis-data:Usage:
- Save as
docker-compose.ymlin your project root (or use the one generated by the scaffolding script). - Create
.env(e.g.,DB_HOST=mysql,REDIS_HOST=redis,DB_DATABASE=laravel). - Add
docker/php/php.ini(e.g.,memory_limit = 256M). - Create
docker/nginx/nginx.confanddocker/nginx/include/fpm-handler.conf(below, or use script-generated versions). - Run
docker-compose up -dand visithttp://localhostorhttp://localhost:8081(phpMyAdmin).
Example docker/nginx/nginx.conf:
server {
listen 80 default_server;
server_name localhost;
client_max_body_size 120M;
access_log /dev/stderr;
error_log /dev/stderr;
root /var/www/public;
index index.php;
# Remove trailing slash
location ~ ^(.+)/$ {
return 301 $1$is_args$args;
}
# Serve static files
location ~* \.(css|js|gif|jpeg|jpg|png|webp|woff2|woff|ico)$ {
root /var/www/public;
add_header X-Serve-Type 'static';
}
# Soketi WebSocket
location /app {
proxy_pass http://soketi:6001;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location / {
include include/fpm-handler.conf;
}
}Example docker/nginx/include/fpm-handler.conf:
add_header X-Serve-Type 'php';
add_header X-Serve-Uri '$uri';
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;Notes:
- Use
8.3-fpmforappto match production. For quick dev, try8.3-cliwithcommand: php artisan serve --host 0.0.0.0 --port 8000and port8000, or use8.3-cli-alpine-octane-swoolefor Octane withcommand: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000. queueandscheduleruse8.3-cliin separate containers, per Docker best practices..:/var/wwwsyncs code for fastcomposer update.- The scaffolding script generates these files automatically.
Add extensions or tweak PHP settings with a custom Dockerfile or volume mounts.
Extend images for extensions like imagick or pgsql. Switch to root for installs, then revert to $user.
Example (Alpine):
FROM ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine
USER root
RUN apk add --no-cache imagemagick-dev && \
pecl install imagick && \
docker-php-ext-enable imagick && \
rm -rf /var/cache/apk/*
USER $userExample (Debian):
FROM ghcr.io/redfieldchristabel/laravel:8.3-cli
USER root
RUN apt-get update && apt-get install -y libpq-dev && \
docker-php-ext-install pgsql && \
apt-get clean && rm -rf /var/lib/apt/lists/*
USER $userExample (Octane with SSL):
FROM ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
USER root
RUN apk add --no-cache openssl-dev && \
pecl install swoole --enable-openssl=yes && \
docker-php-ext-enable swoole && \
rm -rf /var/cache/apk/*
USER $userUsage:
- Save
Dockerfilein project root. - Update
docker-compose.yml:services: app: build: context: . dockerfile: Dockerfile volumes: - .:/var/www
- Run
docker-compose up -d --build.
Tweak php.ini (e.g., memory_limit):
- Create
docker/php/php.ini:memory_limit = 256M upload_max_filesize = 64M
- Mount in
docker-compose.yml:volumes: - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
Note: Use default entrypoints for PHP images (docker-entrypoint.sh) to handle setup and logging. The installer uses laravel directly, and Octane uses docker-php-entrypoint for octane:start.
For production, use fpm or fpm-alpine with Nginx, copying the codebase into the image for speed and mounting only ./vendor:/var/www/vendor. For Octane, use cli-alpine-octane-swoole or cli-debian-octane-swoole. The non-root laravel user ensures safety. Two docker-compose.yml options: standard or with Kong API Gateway. These files are generated by the scaffolding script as prod.docker-compose.yml.
version: '3.8'
services:
app:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
ports:
- "80:8000"
depends_on:
- mysql
- redis
env_file:
- .env.production
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
retries: 3
timeout: 10s
queue:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "queue:work", "--queue=high,default"]
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env.production
scheduler:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "schedule:work"]
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env.production
mysql:
image: mysql:8.0
volumes:
- mysql-data:/var/lib/mysql
env_file:
- .env.production
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
retries: 3
timeout: 10s
redis:
image: redis:alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
retries: 3
timeout: 10s
volumes:
mysql-data:
redis-data:Uses Kong for routing, authentication, and rate-limiting, with Octane as the backend.
version: '3.8'
services:
app:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli-alpine-octane-swoole
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- mysql
- redis
env_file:
- .env.production
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
retries: 3
timeout: 10s
queue:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "queue:work", "--queue=high,default"]
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env.production
scheduler:
image: ghcr.io/redfieldchristabel/laravel:8.3-cli
command: ["php", "artisan", "schedule:work"]
volumes:
- ./vendor:/var/www/vendor
- ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
depends_on:
- app
- mysql
- redis
env_file:
- .env.production
kong:
image: kong:latest
environment:
KONG_DATABASE: "off"
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: "0.0.0.0:8001"
ports:
- "80:8000"
- "443:8443"
- "8001:8001"
volumes:
- ./docker/kong/kong.yml:/usr/local/kong/declarative/kong.yml:ro
depends_on:
- app
networks:
- kong
mysql:
image: mysql:8.0
volumes:
- mysql-data:/var/lib/mysql
env_file:
- .env.production
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 30s
retries: 3
timeout: 10s
redis:
image: redis:alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
retries: 3
timeout: 10s
networks:
kong:
external: true
volumes:
mysql-data:
redis-data:Example docker/kong/kong.yml:
_format_version: "3.0"
services:
- name: laravel-app
url: http://app:8000
routes:
- name: laravel-route
paths:
- /Production Usage:
- Run
composer install --no-dev --optimize-autoloaderlocally to generatevendor. - Copy
vendor,public,docker/,.env.productionto the server. - For Kong, add
docker/kong/kong.yml. - Run
docker-compose -f prod.docker-compose.yml up -d(generated by the scaffolding script). - Access at
http://<server-ip>(standard) or Kongβs proxy.
Notes:
- Standard: Octane on port 8000 (no Nginx needed for Octane).
- Kong: Proxies via Kong; configure
kong.ymlfor auth/rate-limiting. - Use
.env.production(e.g.,APP_ENV=production,DB_HOST=mysql). - Mount only
./vendor:/var/www/vendorfor security. - Healthchecks and stdout logs ensure reliability.
- The scaffolding script generates
prod.docker-compose.ymlfor this setup.
Questions or ideas? Open an issue at redfieldchristabel/laravel-dockerize. Pull requests are welcome! Join us to make Laravel + Docker even better! π
Happy coding with Laravel! ππ