Deploying applications with Docker has revolutionized the way developers build, ship, and run software. Laravel, a popular PHP framework known for its elegant syntax and powerful features, pairs exceptionally well with Docker to create a consistent and scalable development and production environment. By leveraging Docker and Docker Compose, you can streamline the deployment process, ensuring that your Laravel application runs smoothly across different environments.

In this guide, we will walk you through the process of deploying a Laravel application using Docker and Docker Compose.

Prerequisites

  • A server running Ubuntu with Docker and Docker Compose installed.
  • A root user or a user with sudo privileges.

Step 1 – Set Up Your Laravel Project

Install PHP and other required packages.

apt install composer php php-cli php-xml php-curl php-intl -y

Stop the Apache service.

systemctl stop apache2

If you don’t have a Laravel project yet, you can create one using Composer:

composer create-project --prefer-dist laravel/laravel laravel-docker

Navigate to the project directory

cd laravel-docker

Step 2 – Create a Dockerfile

Create a Dockerfile in the root of your Laravel project. This file defines the image configuration for your Laravel application.

nano Dockerfile

Add the following lines:

# Use the official PHP image as a base image
FROM php:8.1-fpm

# Set working directory
WORKDIR /var/www

# Install system dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libzip-dev \
    libpq-dev \
    libonig-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd

# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql pdo_pgsql mbstring zip exif pcntl

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Copy the existing application directory contents to the working directory
COPY . /var/www

# Copy the existing application directory permissions to the working directory
COPY --chown=www-data:www-data . /var/www

# Change current user to www
USER www-data

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

Save and close the file.

Step 3 – Create a Docker Compose File

Create a docker-compose.yml file in the root of your project. This file defines the services (containers) to be run.

nano docker-compose.yml

Add the following configuration:

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: laravel-app
    container_name: laravel-app
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes:
      - .:/var/www
      - ./docker-compose/php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - app-network

  webserver:
    image: nginx:alpine
    container_name: nginx-webserver
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - .:/var/www
      - ./docker-compose/nginx:/etc/nginx/conf.d/
    networks:
      - app-network

  db:
    image: mysql:5.7
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_ROOT_PASSWORD: root
      MYSQL_PASSWORD: root
      MYSQL_USER: root
    ports:
      - "3306:3306"
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  dbdata:
    driver: local

Save and close the file.

Step 4 – Configure Nginx

Create a directory named docker-compose/nginx and add a configuration file named default.conf inside it.

mkdir -p docker-compose/nginx 
nano docker-compose/nginx/default.conf

Add the following configuration.

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;
    }
}

Save the file.

Step 5 – Environment Variables

Ensure you have a .env file set up in your Laravel project with appropriate configurations. For instance, set the database host to db (the name of the MySQL service in docker-compose.yml):

nano .env

Modify the following content:

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=root

Step 6 – Build and Run the Containers

Build and start the Docker containers using Docker Compose:

docker-compose up -d

This command will build the Docker images defined in the Dockerfile and docker-compose.yml, and then start the containers in detached mode.

Verify the running containers.

docker-compose ps

Output.

     Name                    Command                 State                     Ports                
----------------------------------------------------------------------------------------------------
laravel-app       docker-php-entrypoint php-fpm    Up           9000/tcp                            
mysql             docker-entrypoint.sh mysqld      Restarting                                       
nginx-webserver   /docker-entrypoint.sh ngin ...   Up           0.0.0.0:8080->80/tcp,:::8080->80/tcp

Step 7 – Access the Application

Your Laravel application should now be accessible at http://your-server-ip:8080.

Step 8 – Stop the Containers

To stop the Docker containers, you can use:

docker-compose down

This will stop and remove the containers but preserve the data stored in the volumes.

Conclusion

You’ve now set up a Laravel application with Docker and Docker Compose. This setup helps isolate the application and its dependencies, making it easier to manage and deploy. You can customize the configuration files further to suit your needs, such as adding more services, adjusting the Nginx configuration, or modifying the PHP environment settings. Try deploying a Laravel app with Docker on dedicated server hosting from Atlantic.Net!