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
laravel
user 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-app
This creates a Laravel 12 app (latest) in ./example-app/
. The image runs laravel
directly, so you just add new example-app
.
Older Versions:
- Use
--version
to 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--api
for 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
laravel
user 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 --install
and 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.ini
for seamless integration. - Sets Up Tools: Downloads helper scripts (
art
,cmpsr
,pint
,nd
,iart
) for Artisan, Composer, Node, and more. - Vite Compatibility: Modifies
vite.config.js
to setserver.host
to"0.0.0.0"
(required for Docker), updating existingserver
blocks or adding a new one. - Environment Setup: Copies
.env.example
to.env
if.env
is missing. - Requirements: Needs
curl
anddocker
installed. 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 theapp
container (useslaravel:8.3-cli
)../art migrate ./art queue:work --queue=high,default
cmpsr
: Run Composer commands in theapp
container../cmpsr install ./cmpsr require laravel/ui
pint
: Run Laravel Pint (code style fixer) in theapp
container../pint ./pint --test
nd
: Run Node.js or npm commands in thevite
container (for Vite-based projects)../nd npm install ./nd npm run dev
iart
: A shortcut for thephp artisan
command, primarily used when you are already inside the container shell (e.g., viadocker exec
or 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.yml
matches 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.js
is 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:
bcmath
ctype
fileinfo
json
mbstring
openssl
pdo
pdo_mysql
tokenizer
xml
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
laravel
directly (e.g.,new example-app
). - octane-swoole π: Runs
php artisan octane:start
via/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-filament
ghcr.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
openssl
by 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 logs
monitoring.
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.yml
in 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.conf
anddocker/nginx/include/fpm-handler.conf
(below, or use script-generated versions). - Run
docker-compose up -d
and visithttp://localhost
orhttp://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-fpm
forapp
to match production. For quick dev, try8.3-cli
withcommand: php artisan serve --host 0.0.0.0 --port 8000
and port8000
, or use8.3-cli-alpine-octane-swoole
for Octane withcommand: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
. queue
andscheduler
use8.3-cli
in separate containers, per Docker best practices..:/var/www
syncs 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 $user
Example (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 $user
Example (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 $user
Usage:
- Save
Dockerfile
in 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-autoloader
locally to generatevendor
. - Copy
vendor
,public
,docker/
,.env.production
to 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.yml
for auth/rate-limiting. - Use
.env.production
(e.g.,APP_ENV=production
,DB_HOST=mysql
). - Mount only
./vendor:/var/www/vendor
for security. - Healthchecks and stdout logs ensure reliability.
- The scaffolding script generates
prod.docker-compose.yml
for 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! ππ