Why Dockerize Your Laravel Application?
Using Docker Compose eliminates "it works on my machine" problems, simplifies team onboarding, and creates portable, reproducible environments for Laravel 12 projects. This setup includes:
- PHP 8.3-FPM (recommended for Laravel 12 in 2026)
- MySQL 8.0
- Nginx as the web server
- Composer pre-installed
- Persistent database storage
Perfect for local development, CI/CD pipelines, or lightweight production in 2026.

Table Of Content
1 Prerequisites
1.) Docker installed → Get Docker
2.) Docker Compose installed → Comes with Docker Desktop
3.) Laravel 12 project (or create new with laravel new project-name)
2 Introduction
- No “works on my machine” issues
- Faster onboarding for teams
- Easy replication of staging/production environments
- Isolation of services (PHP, DB, Cache, etc.)
3 Project structure
Example directory layout:
Tip: Many developers keep Laravel code in a src/ subfolder for cleaner separation.
4 Create Dockerfile for PHP
FROM php:8.3-fpm
# Install dependencies
RUN apt-get update && apt-get install -y \
git curl libpng-dev libjpeg-dev libfreetype6-dev zip unzip \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd pdo pdo_mysql mbstring exif pcntl bcmath
# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
# Copy application code (adjust path if not using ./src)
COPY ./src /var/www
# Permissions & best practices
RUN chown -R www-data:www-data /var/www \
&& chmod -R 755 /var/www/storage /var/www/bootstrap/cache
# Expose PHP-FPM port
EXPOSE 9000
CMD ["php-fpm"]
5 Create docker-compose.yml
version: "3.9"
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel_app
volumes:
- ./src:/var/www
depends_on:
- mysql
networks:
- laravel_net
mysql:
image: mysql:8.0
container_name: laravel_mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- laravel_net
nginx:
image: nginx:alpine
container_name: laravel_nginx
ports:
- "8000:80"
volumes:
- ./src:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
networks:
- laravel_net
networks:
laravel_net:
driver: bridge
volumes:
mysql_data:
6 Configure Nginx
server {
listen 80;
index index.php index.html;
server_name localhost;
root /var/www/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
7 Update Laravel .env File
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
8 Build and Start the Containers
docker-compose up -d --build
- Laravel app runs inside app container
- MySQL runs in mysql container
- Nginx serves the app on http://localhost:8000
9 Install Dependencies & Run Migrations
# Enter the PHP container
docker compose exec app bash
Then install:
# Inside the container:
composer install --optimize-autoloader --no-dev
php artisan key:generate
php artisan migrate --force
php artisan storage:link
10 Verify Setup
Open your browser and visit: http://localhost:8000
You should see the Laravel welcome page. Success!
12 Troubleshooting & Best Practices
- Port conflict? Change ports in docker-compose.yml (e.g., "8080:80").
- Storage permissions? Run
chmod -R 777 storage bootstrap/cacheinside container. - MySQL connection failed? Confirm
DB_HOST=mysql(service name, not localhost). - Add Redis/Queue? Add a
redisservice similarly. - Production tips: Use multi-stage builds, Docker secrets, remove
portsfor MySQL, enable healthchecks. - Alternative: Try Laravel Sail for an even simpler official Docker setup.
Written by Revathi M
PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel
Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.
Frequently Asked Questions
You need Docker and Docker Compose installed, and a Laravel 12 project created using 'laravel new project-name'.
The services include 'app' (custom PHP-FPM build), 'mysql' (mysql:8.0 image), and 'nginx' (nginx:latest image).
Set DB_HOST=mysql, DB_PORT=3306, DB_DATABASE=laravel, DB_USERNAME=laravel, and DB_PASSWORD=secret.
Run 'docker-compose up -d --build' in the project root.
Exec into the app container with 'docker exec -it laravel_app bash', then run 'composer install'.
After accessing the container, run 'php artisan migrate'. Also generate the app key with 'php artisan key:generate'.
Nginx exposes port 8000 (host) to 80 (container), and MySQL exposes 3306 for external access if needed.
A named volume 'mysql_data' is mounted to /var/lib/mysql in the MySQL container.
