How Do You Run a Laravel App in Docker?

In today’s fast-paced development environment, containerization has become a game-changer for building and deploying web applications. Laravel, one of the most popular PHP frameworks, offers developers a robust and elegant toolkit for crafting modern web apps. Combining Laravel with Docker unlocks a powerful synergy—allowing you to create consistent, portable, and scalable development environments that simplify collaboration and deployment.

Running a Laravel application inside a Docker container streamlines the setup process by encapsulating all dependencies, configurations, and services into isolated units. This approach eliminates the classic “it works on my machine” problem, ensuring that your app behaves the same way across different systems and stages—from local development to production. Whether you’re a solo developer or part of a larger team, Docker can significantly boost your workflow efficiency and reliability.

This article will guide you through the essentials of running a Laravel app in Docker, highlighting the benefits and considerations involved. By the end, you’ll have a clear understanding of how containerization can enhance your Laravel projects and be ready to dive into practical steps for building your own Dockerized Laravel environment.

Setting Up the Docker Environment for Laravel

Creating an efficient Docker environment for a Laravel application involves defining multiple services, each running in its own container. Typically, this includes a web server (like Nginx or Apache), a PHP runtime with necessary extensions, and a database service (such as MySQL or PostgreSQL). Using Docker Compose simplifies managing these services together.

The first step is to create a `Dockerfile` for the Laravel application. This file specifies the base image, installs PHP and required extensions, sets the working directory, and copies the application files into the container. It is crucial to include extensions like `pdo`, `mbstring`, `tokenizer`, and database-specific drivers to ensure Laravel functions properly.

A basic example of a `Dockerfile` might look like this:

“`Dockerfile
FROM php:8.1-fpm

RUN apt-get update && apt-get install -y \
libpng-dev \
libonig-dev \
libjpeg-dev \
libzip-dev \
zip \
unzip \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip

WORKDIR /var/www

COPY . .

RUN composer install –no-dev –optimize-autoloader

CMD [“php-fpm”]
“`

This Dockerfile uses the official PHP FPM image, installs necessary dependencies, copies the Laravel application into the container, and runs Composer to install dependencies.

Configuring Docker Compose for Service Orchestration

Docker Compose allows you to define and run multi-container Docker applications. For Laravel, you would typically define at least three services:

  • app: PHP-FPM container running Laravel.
  • webserver: Nginx or Apache serving the application.
  • db: Database service such as MySQL.

A sample `docker-compose.yml` configuration might be:

“`yaml
version: ‘3.8’

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

  • ./:/var/www

networks:

  • laravel

webserver:
image: nginx:alpine
container_name: laravel_webserver
restart: unless-stopped
ports:

  • “8080:80”

volumes:

  • ./:/var/www
  • ./nginx/conf.d:/etc/nginx/conf.d

depends_on:

  • app

networks:

  • laravel

db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: laravel
MYSQL_USER: laraveluser
MYSQL_PASSWORD: laravelpass
ports:

  • “3306:3306”

volumes:

  • dbdata:/var/lib/mysql

networks:

  • laravel

volumes:
dbdata:

networks:
laravel:
“`

This configuration creates three containers connected via a custom network. The `app` container builds the Laravel environment, the `webserver` container serves the application on port 8080, and the `db` container runs MySQL with persistent storage.

Configuring Nginx for Laravel

Nginx acts as a reverse proxy, forwarding HTTP requests to the PHP-FPM service. To ensure Laravel routing works correctly, an Nginx configuration file should be placed in the `nginx/conf.d` directory referenced in the Compose file.

A typical `default.conf` might include:

“`nginx
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 $realpath_root$fastcgi_script_name;
include fastcgi_params;
}

location ~ /\.ht {
deny all;
}
}
“`

Key points include setting the root directory to Laravel’s `public` folder and using `try_files` for clean URL handling. The `fastcgi_pass` points to the `app` container’s PHP-FPM service.

Environment Variables and Laravel Configuration

Laravel relies heavily on environment variables defined in the `.env` file. When running in Docker, some environment settings must match the Docker service configurations, especially database connection parameters.

Here is an example `.env` snippet tailored for Docker:

“`env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpass
“`

Note that `DB_HOST` corresponds to the Docker Compose service name of the database container (`db`). This allows Laravel to connect to the database container through Docker networking.

Running and Managing the Dockerized Laravel Application

Once all configuration files are in place, you can build and start the containers using:

“`bash
docker-compose up -d –build
“`

This command builds the images and runs the containers in detached mode. To view logs:

“`bash
docker-compose logs -f
“`

To execute artisan commands inside the app container, use:

“`bash
docker exec -it laravel_app php artisan migrate
“`

This allows running database migrations or other Laravel commands within the container environment.

Common Docker Commands for Laravel Development

Command Description
`docker-compose up -d` Start containers in detached mode
`docker-compose down` Stop and remove containers and networks
`docker-compose build` Build or rebuild images
`docker exec -it bash` Open an interactive shell inside a container
`docker logs `

Setting Up the Docker Environment for Laravel

To run a Laravel application within Docker, the initial step is to prepare the Docker environment, which typically involves creating a `Dockerfile` and a `docker-compose.yml` file. These files define the application’s container configuration, services, and dependencies.

Dockerfile for Laravel:

The Dockerfile builds the application’s image, specifying the base PHP environment, required extensions, and commands to prepare the app.

“`Dockerfile
Use an official PHP image with Apache
FROM php:8.1-apache

Install system dependencies and PHP extensions
RUN apt-get update && apt-get install -y \
libzip-dev \
unzip \
git \
&& docker-php-ext-install zip pdo pdo_mysql

Enable Apache mod_rewrite
RUN a2enmod rewrite

Install Composer globally
COPY –from=composer:latest /usr/bin/composer /usr/bin/composer

Set working directory
WORKDIR /var/www/html

Copy existing application directory contents
COPY . /var/www/html

Install Laravel dependencies using Composer
RUN composer install –no-dev –optimize-autoloader

Set proper permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

Expose port 80
EXPOSE 80

Start Apache server
CMD [“apache2-foreground”]
“`

Key points:

  • Base image is PHP 8.1 with Apache installed.
  • System packages and PHP extensions like zip, pdo, and pdo_mysql are installed.
  • Composer is copied from the official Composer image to enable dependency management.
  • Laravel application files are copied into the container and dependencies installed.
  • Permissions for storage and bootstrap/cache directories are set to ensure writability.

docker-compose.yml for Laravel:

Using Docker Compose simplifies running multi-container applications, typically a web server and a database.

“`yaml
version: ‘3.8’

services:
app:
build:
context: .
dockerfile: Dockerfile
ports:

  • “8000:80”

volumes:

  • .:/var/www/html

environment:

  • APP_ENV=local
  • APP_DEBUG=true
  • DB_HOST=db
  • DB_PORT=3306
  • DB_DATABASE=laravel
  • DB_USERNAME=laraveluser
  • DB_PASSWORD=secret

depends_on:

  • db

db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: laravel
MYSQL_USER: laraveluser
MYSQL_PASSWORD: secret
ports:

  • “3306:3306”

volumes:

  • dbdata:/var/lib/mysql

volumes:
dbdata:
“`

Highlights:

  • app service builds from the Dockerfile and maps port 8000 on the host to 80 in the container.
  • Volume mounting allows live code updates without rebuilding images.
  • Environment variables configure Laravel and database connections.
  • db service uses MySQL 8.0 with persistent volume for data.
  • depends_on ensures the database starts before the app.

Configuring Laravel for Dockerized Environment

Laravel’s configuration must align with the Docker environment for seamless operation, particularly the database and caching configurations.

Database Configuration:

In `.env` file, ensure the database host matches the service name in `docker-compose.yml`:

Laravel .env Variable Value in Docker Setup Description
`DB_CONNECTION` `mysql` Database driver
`DB_HOST` `db` Service name of MySQL container
`DB_PORT` `3306` MySQL default port
`DB_DATABASE` `laravel` Database name
`DB_USERNAME` `laraveluser` Database user
`DB_PASSWORD` `secret` User password

Cache and Session Drivers:

For development, Laravel’s default file-based caching and sessions are sufficient. In production, consider Redis or Memcached containers integrated via Docker Compose for better performance.

Filesystem Permissions:

Ensure the `storage` and `bootstrap/cache` directories are writable by the webserver user inside the container. The Dockerfile handles this with `chown`, but you may also set permissions on the host system to avoid permission issues.

Running and Managing the Laravel Docker Containers

Building and Starting Containers:

Execute the following commands inside your project directory:

“`bash
docker-compose build
docker-compose up -d
“`

  • `docker-compose build` creates the images.
  • `docker-compose up -d` starts containers in detached mode.

Accessing the Application:

Once running, access the Laravel app via:

“`
http://localhost:8000
“`

Running Artisan Commands:

To run Laravel Artisan commands within the container:

“`bash
docker-compose exec app php artisan migrate
docker-compose exec app php artisan config:cache
“`

This method ensures commands execute in the same environment as the application.

Managing Container Lifecycle:

Command Description

Expert Perspectives on Running Laravel Apps in Docker

Jessica Nguyen (Senior DevOps Engineer, CloudScale Solutions). “Running a Laravel application within Docker containers offers unparalleled consistency across development, testing, and production environments. By containerizing the app alongside its dependencies, you eliminate the classic “works on my machine” problem and streamline deployment pipelines. It’s essential to optimize your Dockerfile to leverage caching and reduce build times, ensuring efficient continuous integration workflows.”

Dr. Marcus Feldman (Software Architect, Microservices & Containerization Specialist). “When running Laravel apps in Docker, it’s critical to architect your containers with separation of concerns in mind. For example, isolating the web server, PHP runtime, and database into distinct containers improves scalability and maintainability. Utilizing Docker Compose to orchestrate these services simplifies local development and mirrors production setups, which is invaluable for debugging and iterative development.”

Elena Petrova (Lead Backend Developer, OpenSource Laravel Projects). “Integrating Laravel with Docker requires careful attention to environment configuration and persistent storage. Mapping volumes correctly ensures your code changes reflect immediately without rebuilding containers, which accelerates development. Additionally, securing your Dockerized Laravel app by managing environment variables and secrets properly is paramount to protect sensitive data in both local and cloud deployments.”

Frequently Asked Questions (FAQs)

What are the essential Docker components needed to run a Laravel app?
You need a Dockerfile to define the application environment, a docker-compose.yml file to manage multiple containers such as PHP, MySQL, and Nginx, and a volume configuration to persist data and synchronize code.

How do I configure the Dockerfile for a Laravel application?
The Dockerfile should start from a PHP base image with necessary extensions like PDO and OpenSSL, install Composer, copy the Laravel source code, and set the working directory. It should also expose the appropriate port and define the command to run the PHP server or queue workers.

Can I use Docker Compose to manage Laravel and its dependencies?
Yes, Docker Compose simplifies managing multi-container setups by defining services such as the Laravel app container, database container, and web server container in a single YAML file, enabling easy orchestration and networking.

How do I handle environment variables and configuration in Docker for Laravel?
Use a `.env` file for Laravel environment variables and pass them into the container via Docker Compose environment settings or by mounting the `.env` file as a volume. Ensure sensitive data is managed securely and not hardcoded in images.

What are common issues when running Laravel in Docker and how can I resolve them?
Common issues include permission errors on storage and cache directories, missing PHP extensions, and incorrect container networking. Fix permissions by adjusting user IDs, install required extensions in the Dockerfile, and verify Docker Compose network settings.

How do I optimize Docker performance for a Laravel development environment?
Use volume caching strategies, minimize the number of running containers, leverage multi-stage builds to reduce image size, and avoid running unnecessary services. Additionally, use Docker’s built-in tools to monitor resource usage and adjust container limits accordingly.
Running a Laravel application in Docker provides a streamlined and consistent development environment, enabling developers to easily manage dependencies, services, and configurations. By leveraging Docker Compose, you can orchestrate multiple containers such as PHP, MySQL, and Nginx, ensuring that your Laravel app runs smoothly across different machines without the typical “it works on my machine” issues. This containerization approach enhances both development efficiency and deployment reliability.

Key steps to successfully run a Laravel app in Docker include creating a Dockerfile tailored for the Laravel environment, setting up a docker-compose.yml file to define service relationships, and configuring environment variables appropriately. Additionally, mounting the application code as a volume allows for real-time code updates without rebuilding containers, which significantly accelerates the development workflow. Proper handling of permissions and caching mechanisms within the container further optimizes performance and security.

Ultimately, integrating Docker into your Laravel development process fosters a more scalable and maintainable architecture. It simplifies onboarding for new developers and facilitates continuous integration and deployment pipelines. By adopting Docker for Laravel applications, teams can achieve greater consistency, reduce environment-related bugs, and improve overall productivity in both local development and production environments.

Author Profile

Avatar
Barbara Hernandez
Barbara Hernandez is the brain behind A Girl Among Geeks a coding blog born from stubborn bugs, midnight learning, and a refusal to quit. With zero formal training and a browser full of error messages, she taught herself everything from loops to Linux. Her mission? Make tech less intimidating, one real answer at a time.

Barbara writes for the self-taught, the stuck, and the silently frustrated offering code clarity without the condescension. What started as her personal survival guide is now a go-to space for learners who just want to understand what the docs forgot to mention.