Docker with Laravel — A Single Environment for Development and Production
> cd .. / HUB_EDITORIALE
Sviluppo di siti web

Docker with Laravel — A Single Environment for Development and Production

[2026-07-13] Author: Ing. Calogero Bono
> share
Zenithby Meteora Web The operating system for your business. Social, clients, bookings and invoices in one platform. Gyms, barbers, professionals. Discover Zenith Free demo · no card

Your Laravel app works perfectly on localhost. You push it to production — and it breaks. Different PHP versions, MySQL configurations, missing extensions. The problem is environment inconsistency. We at Meteora Web have seen clients waste days debugging environment mismatches. Docker solves this by creating one identical environment for every stage. For Laravel, the setup is clean, fast, and production-ready.

Why use Docker with Laravel for development and production?

Let’s start with a real scenario: your local machine runs PHP 8.3, the server runs PHP 8.1. A function deprecated in 8.1 works locally but crashes in production. Or your local database is MariaDB, the server is MySQL 5.7 — queries behave differently. Docker eliminates these issues by using the same image everywhere. We use Docker for every Laravel project we build: the environment is versioned alongside the code, not left to memory.

The real benefits we see daily

  • No more "it works on my machine" — environment is 100% replicable.
  • Onboard new developers in minutes — clone the repo, run docker compose up -d, done. No manual PHP/MySQL/Node setup.
  • Production matches development — same docker-compose.yml with minor environment overrides.
  • Saves hours of debugging — environment differences cause most production bugs.

Coming from a background in accounting and ERP systems, we frame this as a cost issue: every hour spent debugging an environment problem is billable time wasted. Docker removes that waste.

Sponsored Protocol

How to set up docker-compose.yml for Laravel?

The docker-compose.yml file defines your services: app (PHP-FPM), web (Nginx), database (MySQL/Postgres), plus optional ones (Redis, Mailpit). Here’s a working example we use for our Laravel projects:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: laravel_app
    restart: unless-stopped
    working_dir: /var/www
    volumes:
      - .:/var/www
      - ./storage:/var/www/storage
    networks:
      - laravel

  web:
    image: nginx:alpine
    container_name: laravel_web
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - .:/var/www
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      - laravel
    depends_on:
      - app

  db:
    image: mysql:8.0
    container_name: laravel_db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3307:3306"
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - laravel

volumes:
  dbdata:

networks:
  laravel:

Practical steps to get it running

1. Create the Dockerfile for the PHP image. This defines how the app service is built:

Sponsored Protocol

FROM php:8.3-fpm-alpine

RUN docker-php-ext-install pdo_mysql bcmath

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www
COPY . .

RUN composer install --no-interaction --prefer-dist --optimize-autoloader

2. Configure Nginx. Create a file called nginx.conf in your project root:

server {
    listen 80;
    index index.php;
    server_name localhost;
    root /var/www/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass app:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

3. Start the environment. From your Laravel project root, run:

Sponsored Protocol

docker compose up -d

Your app will be available at http://localhost:8080.

How to optimize the Docker image for production?

For production, the image must be small, secure, and ready to run. The golden rule: do not include Composer, npm, or build tools in the final image. Use a multi-stage build to separate the build phase from the runtime phase.

Multi-stage Dockerfile example

# Stage 1: Build
FROM php:8.3-cli-alpine AS build

WORKDIR /app
COPY . .

RUN docker-php-ext-install pdo_mysql bcmath
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer install --no-dev --optimize-autoloader

# Stage 2: Runtime
FROM php:8.3-fpm-alpine

COPY --from=build /app /var/www

RUN docker-php-ext-install pdo_mysql bcmath opcache

COPY php.ini-production /usr/local/etc/php/php.ini

WORKDIR /var/www

With multi-stage, the final image is ~200 MB instead of over 1 GB. We use this for every deployment — it reduces storage costs and speeds up pull times on servers.

Sponsored Protocol

How to manage environment variables in development vs production?

Laravel uses the .env file. In development, mount it as a volume. In production, embed it in the image or inject via container environment variables. The cleanest approach: have a separate .env.production file and copy it to .env during CI/CD before building the image.

Practical scheme

  • Development: .env file mounted as volume. Database points to db:3306.
  • Production: .env generated by CI/CD pipeline with real values (remote database, API keys). Never committed to the repo.
  • Key differences: APP_ENV=production, APP_DEBUG=false, different DB_HOST.
# On the production server, run:
docker run -d --env-file .env.production my-laravel-app:latest

Should you use Laravel Sail for development?

Laravel Sail is an official Docker wrapper. We recommend it to clients who don’t want to write Docker files manually. Sail handles MySQL, Redis, Mailhog with a single command: sail up -d. It’s great for development. For production, we prefer a custom setup with multi-stage builds and server-specific optimizations.

Sponsored Protocol

When we skip Sail

Sail gives you less control over the production image. We built a proprietary platform for managing multiple client sites: to optimize hosting costs and performance, we use custom multi-stage images with Nginx built in. Sail doesn’t support multi-stage natively and requires a separate Nginx container. For small projects, Sail is fine. For scalability, custom wins.

What to do now

  1. Get a Laravel test project — if you don’t have one, run composer create-project laravel/laravel test-docker.
  2. Copy the files (docker-compose.yml, Dockerfile, nginx.conf) from this guide — adapt them to your project.
  3. Start the environment with docker compose up -d and test at localhost:8080.
  4. Test the differences — change a production variable (e.g. APP_DEBUG=false) and verify the behavior changes.
  5. Document the setup — if you work in a team, add a README.md with the basic commands. It will reduce onboarding time to minutes.

For the full picture, read our main guide on Docker and Containerization for Italian SMEs. For official Laravel docs on Sail, check the Laravel documentation.

> share
Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere informatico, fondatore di Meteora Web e Zenith OS. System administrator e progettista di piattaforme, app e CMS proprietari, con esperienza in sviluppo full-stack, marketing digitale ed ecosistema Google.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.

> MW_JOURNAL

> READ_ALL()