Dockerize Laravel App: Step-by-step Guide
Summary:
Create Dockerfile and docker-compose for Laravel app.
Dockerizing your Laravel application enables consistent development environments, effortless deployments, and simplified scalability. Whether you’re deploying to the cloud or simply seeking to standardize your team’s development stack, containerizing Laravel is a wise move. In this step-by-step tutorial, we’ll cover how to create a Dockerfile
and a docker-compose.yml
file tailored for a modern Laravel application.
Table of Contents
- Prerequisites
- Laravel Project Structure
- Create Dockerfile
- Create docker-compose.yml
- Adding Environment Variables
- Build and Run Containers
- Extra: Dockerizing Queue Workers & Scheduler
- Conclusion
Prerequisites
- Basic understanding of Docker and Laravel
- Docker and Docker Compose installed (Installation Guide)
- A Laravel application (or create one with
composer create-project laravel/laravel example-app
)
Laravel Project Structure
Here’s a typical Laravel folder structure (trimmed for clarity):
laravel-app/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
├── resources/
├── routes/
├── storage/
├── tests/
├── artisan
├── composer.json
├── package.json
└── ...
After you place your Laravel project inside a directory (e.g., laravel-app
), you’ll be working from this location.
Create Dockerfile
The Dockerfile defines the application runtime environment for Laravel. Here’s a standard Dockerfile using PHP 8.2, Composer, and Node.js for asset compilation with npm.
# Dockerfile
FROM php:8.2-fpm
# Install system dependencies and PHP extensions
RUN apt-get update && apt-get install -y \
git curl libpng-dev libonig-dev libxml2-dev zip unzip npm \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Install Composer globally
COPY --from=composer:2.5 /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy application files
COPY . .
# Install dependencies
RUN composer install --optimize-autoloader --no-dev
RUN npm install && npm run build
# Copy existing application key, storage and vendor folder permissions
RUN chown -R www-data:www-data /var/www \
&& chmod -R 755 /var/www/storage
EXPOSE 9000
CMD ["php-fpm"]
Explanation
- FROM php:8.2-fpm: Uses the official PHP FPM image as base.
- Install dependencies: Adds required libraries and PHP extensions.
- Install Composer: Pulls Composer from its image.
- WORKDIR: Sets
/var/www
as the working directory. - COPY . .: Copies all app files into the container.
- Install dependencies: Runs
composer install
andnpm install && npm run build
. - Permissions: Properly sets permissions for the storage directory.
- EXPOSE: Exposes port 9000 (default for PHP-FPM).
Create docker-compose.yml
docker-compose.yml
orchestrates multiple services — PHP (your app), MySQL, and Nginx.
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: laravel-app
container_name: laravel-app
restart: unless-stopped
volumes:
- ./:/var/www
environment:
- DB_HOST=db
- DB_DATABASE=laravel
- DB_USERNAME=laravel
- DB_PASSWORD=secret
depends_on:
- db
nginx:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
ports:
- "8000:80"
volumes:
- ./:/var/www
- ./docker/nginx/conf.d/:/etc/nginx/conf.d/
depends_on:
- app
db:
image: mysql:8.0
container_name: mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: root
ports:
- "3306:3306"
volumes:
- dbdata:/var/lib/mysql
volumes:
dbdata:
Nginx Configuration
Create a folder docker/nginx/conf.d
and add a file called default.conf
:
# docker/nginx/conf.d/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$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/public$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Adding Environment Variables
Copy .env.example
to .env
:
cp .env.example .env
In your .env
file, set the database credentials to match docker-compose.yml
:
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
Generate the application key:
docker-compose run --rm app php artisan key:generate
Build and Run Containers
-
Build and run all services:
docker-compose up --build -d
-
Access your app at http://localhost:8000.
-
Run migrations:
docker-compose exec app php artisan migrate
-
View logs:
docker-compose logs -f app
Stop and remove containers:
docker-compose down
Extra: Dockerizing Queue Workers & Scheduler
If your app uses queues or scheduled jobs, add worker and scheduler services to docker-compose.yml
:
queue:
build:
context: .
dockerfile: Dockerfile
command: php artisan queue:work
volumes:
- ./:/var/www
depends_on:
- db
- app
scheduler:
build:
context: .
dockerfile: Dockerfile
command: php artisan schedule:work
volumes:
- ./:/var/www
depends_on:
- db
- app
Conclusion
Dockerizing your Laravel application simplifies setup, boosts portability, and streamlines deployment. With a custom Dockerfile
and docker-compose.yml
, your development and production environments become consistent and easy to manage. Expand your setup by adding cache and session stores, custom worker images, or secure secrets management as needed.
Happy shipping with Docker and Laravel!