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.



Docker Compose for Laravel 12 + MySQL: Complete Setup Guide

Table Of Content

1 Prerequisites

Make sure you have:
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

Docker simplifies Laravel development by standardizing the environment. Instead of manually installing PHP, MySQL, Composer, and Nginx on your machine, you can run your Laravel app inside containers. Benefits include:
  • 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

Create: docker/php/Dockerfile

   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

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

Create file: docker/nginx/default.conf

    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

Update database section in .env

   DB_CONNECTION=mysql
    DB_HOST=mysql
    DB_PORT=3306
    DB_DATABASE=laravel
    DB_USERNAME=laravel
    DB_PASSWORD=secret

8 Build and Start the Containers

Run:

  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

Open the container:

     # 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/cache inside container.
  • MySQL connection failed? Confirm DB_HOST=mysql (service name, not localhost).
  • Add Redis/Queue? Add a redis service similarly.
  • Production tips: Use multi-stage builds, Docker secrets, remove ports for MySQL, enable healthchecks.
  • Alternative: Try Laravel Sail for an even simpler official Docker setup.
Revathi M - PHP and CodeIgniter Developer

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.