Skip to content

Modern Laravel 10 Deployment with Docker (2024–2025 Best Practices)

  • Best Practice

πŸš€ A modern, production-friendly approach to running Laravel 10 with Docker on Ubuntu 22.04 / 24.04 β€” cleaner, safer, and easier to maintain.

  • Laravel 10
  • PHP-FPM 8.1+
  • MySQL 8.0
  • phpMyAdmin (optional, non-production)
  • Nginx (Reverse Proxy)
  • Docker Compose v2

  • No static container IPs
  • No exposed database ports (internal network only)
  • Environment variables via .env
  • Named volumes for persistence
  • Docker Compose v2 (docker compose)
  • phpMyAdmin marked as optional / non-prod

🐳 Step 1 β€” Install Docker Engine (Official Method)

Section titled β€œπŸ³ Step 1 β€” Install Docker Engine (Official Method)”
Terminal window
sudo apt update -y
sudo apt install -y ca-certificates curl gnupg
Terminal window
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Terminal window
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update -y
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verify:

Terminal window
docker version
docker compose version

  • Directorylaravel-docker/
    • Directoryapp/ # Laravel source code
      • …
    • Directorydocker/
      • Directorynginx/
        • default.conf
      • Directoryphp/
        • Dockerfile
        • php.ini
    • docker-compose.yml
    • .env

πŸ” Step 3 β€” Environment Configuration (.env)

Section titled β€œπŸ” Step 3 β€” Environment Configuration (.env)”
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret

docker/php/Dockerfile:

FROM php:8.1-fpm
RUN apt-get update && apt-get install -y \
git curl zip unzip libpng-dev libonig-dev libxml2-dev \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html

🧩 Step 5 β€” docker-compose.yml (Clean & Modern)

Section titled β€œπŸ§© Step 5 β€” docker-compose.yml (Clean & Modern)”
services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel-app
volumes:
- ./app:/var/www/html
env_file:
- .env
depends_on:
- db
web:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
volumes:
- ./app:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
db:
image: mysql:8.0
container_name: mysql
restart: always
environment:
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
volumes:
- dbdata:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
container_name: phpmyadmin
ports:
- "8081:80"
environment:
PMA_HOST: db
profiles:
- debug
volumes:
dbdata:

docker/nginx/default.conf:

server {
listen 80;
index index.php index.html;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

Terminal window
docker compose up -d --build

Generate Laravel key:

Terminal window
docker compose exec app php artisan key:generate

Access the app:


  • Use .env.production
  • Disable phpMyAdmin
  • Add HTTPS (Traefik / Nginx + Certbot)
  • Use non-root containers if needed
  • Consider queue & scheduler containers

This setup is intentionally boring β€” and that’s a good thing.
Simple Compose files, predictable networking, and fewer moving parts mean fewer 3 AM incidents.

If you’re migrating from an older Laravel Docker setup, this structure is a solid baseline going forward.