If you are a Laravel developer, you are probably used to local development stacks like Laragon, Valet, or Herd. While those work well on a single machine, issues crop up the moment you collaborate with a team, switch OS environments, or prepare your project for a production server: "It works on my machine" syndrome.
Here is a straightforward guide to understanding Docker and using it to run your Laravel applications.
1. What is Docker? The Core Mental Model
Think of a Docker container as a lightweight, isolated virtual box that packages your application along with its dependencies—PHP, extensions, Nginx, and databases. Because everything is defined in code, it runs identically on any system.
To understand Docker, you only need three core concepts:
- Dockerfile: The blueprint or recipe. A plain text file defining the base operating system, packages, and PHP extensions your application needs.
- Image: The compiled, read-only snapshot built from your Dockerfile.
- Container: The running instance of an Image. You can start, stop, and destroy containers without affecting the underlying image.
2. Essential Docker Commands
These cover roughly 90% of your day-to-day work:
# Run a container in detached mode (-d) and map port 8080 on your host to port 80 inside the container (-p)
docker run -d -p 8080:80 --name my-web-server nginx
# List all currently running containers
docker ps
# List all containers (running and stopped)
docker ps -a
# Stop and remove a container
docker stop my-web-server
docker rm my-web-server
# List downloaded local images
docker images
3. Running Laravel with Docker: Two Approaches
When containerizing Laravel, you have two primary options: Laravel Sail (ideal for rapid local development) and a Custom Dockerfile + Docker Compose setup (ideal for production parity and granular control).
Option A: Laravel Sail (The Quick Path)
Laravel Sail is Laravel’s official, pre-configured Docker development environment.
- Install Sail in an existing Laravel project:
composer require laravel/sail --dev
php artisan sail:install
Select your preferred services (e.g., mysql, redis, mailpit).
- Start your containers:
./vendor/bin/sail up -d
- Run commands inside the environment:
./vendor/bin/sail artisan migrate
./vendor/bin/sail composer require laravel/sanctum
Option B: Custom Docker Setup (Full Control)
If you want complete control over your stack or need an architecture that transitions directly into production, set up your own multi-container environment using Docker Compose.
Place the following three files in the root directory of your Laravel application:
1. Dockerfile (PHP 8.3-FPM + Extensions)
FROM php:8.3-fpm-alpine
# Install system dependencies & PHP build tools
RUN apk add --no-cache \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
mysql-client
# Install required PHP extensions
RUN docker-php-ext-install pdo pdo_mysql mbstring exif pcntl bcmath gd
# Install Composer directly from its official image
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
EXPOSE 9000
CMD ["php-fpm"]
2. nginx.conf (Web Server Configuration)
server {
listen 80;
index index.php index.html;
root /var/www/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
3. docker-compose.yml (Orchestrating PHP, Nginx, and MySQL)
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: laravel-app
restart: unless-stopped
working_dir: /var/www
volumes:
- ./:/var/www
networks:
- laravel-net
web:
image: nginx:alpine
container_name: laravel-web
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- laravel-net
db:
image: mysql:8.0
container_name: laravel-db
restart: unless-stopped
environment:
MYSQL_DATABASE: laravel_db
MYSQL_USER: laravel_user
MYSQL_PASSWORD: secret_password
MYSQL_ROOT_PASSWORD: root_password
ports:
- "3306:3306"
volumes:
- db_data:/var/lib/mysql
networks:
- laravel-net
networks:
laravel-net:
driver: bridge
volumes:
db_data:
4. Connecting and Running
-
Update your
.envfile: Inside Docker networks, containers communicate using their service names as hostnames. ChangeDB_HOSTfrom127.0.0.1todb:
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=secret_password
- Build and start the services:
docker compose up -d --build
- Run your migrations:
docker compose exec app php artisan migrate
Open http://localhost:8000 in your browser. Your Laravel application is now fully running inside isolated, reproducible containers.
Top comments (0)