Build and Deploy Laravel Apps Like a Pro: CI/CD with Docker, Nginx & GitHub Actions


Deploying Laravel applications efficiently is critical to ensuring performance, scalability, and maintainability. In this guide, you’ll learn how to build a complete CI/CD pipeline using Docker, Nginx, and GitHub Actions to automate deployment and streamline your Laravel development lifecycle.


 Why CI/CD Matters for Laravel Applications

Continuous Integration (CI) and Continuous Deployment (CD) allow developers to:

  • Automatically build, test, and deploy code

  • Reduce human error in deployment processes.

  • Maintain consistent environments across development, staging, and production.

  • Accelerate release cycles and improve developer productivity.


 Project Structure Overview

Here's a sample directory structure for your Laravel project with Docker and Nginx:


laravel-app/

├── app/

├── bootstrap/

├── config/

├── database/

├── docker/

│   ├── nginx/

│   │   └── default.conf

│   └── php/

│       └── Dockerfile

├── .github/

│   └── workflows/

│       └── ci-cd.yml

├── .env

├── docker-compose.yml

└── artisan



Step 1: Dockerize Your Laravel App

Dockerfile (PHP)


FROM php:8.2-fpm


WORKDIR /var/www


RUN apt-get update && apt-get install -y \

    git curl zip unzip libzip-dev \

    && docker-php-ext-install pdo_mysql zip


COPY . .


RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \

    && composer install


docker-compose.yml


version: '3.8'


services:

  app:

    build:

      context: .

      dockerfile: docker/php/Dockerfile

    container_name: laravel-app

    volumes:

      - .:/var/www

    networks:

      - laravel


  nginx:

    image: nginx:latest

    ports:

      - 80:80

    volumes:

      - .:/var/www

      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf

    depends_on:

      - app

    networks:

      - laravel


networks:

  laravel:

    driver: bridge


Nginx Configuration (default.conf)


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;

        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

        fastcgi_param DOCUMENT_ROOT $realpath_root;

    }


    location ~ /\.ht {

        deny all;

    }

}



Step 2: Set Up GitHub Actions for CI/CD

.github/workflows/ci-cd.yml


name: Laravel CI/CD Pipeline


on:

  push:

    branches: [main]


jobs:

  build-and-deploy:

    runs-on: ubuntu-latest


    services:

      mysql:

        image: mysql:5.7

        env:

          MYSQL_ROOT_PASSWORD: password

          MYSQL_DATABASE: laravel

        ports:

          - 3306:3306

        options: >-

          --health-cmd="mysqladmin ping --silent"

          --health-interval=10s

          --health-timeout=5s

          --health-retries=3


    steps:

    - name: Checkout Repository

      uses: actions/checkout@v3


    - name: Set Up PHP

      uses: shivammathur/setup-php@v2

      with:

        php-version: '8.2'


    - name: Install Dependencies

      run: |

        composer install

        cp .env.example .env

        php artisan key:generate


    - name: Run Tests

      run: php artisan test


    - name: Deploy to Server

      if: success()

      uses: appleboy/ssh-action@master

      with:

        host: ${{ secrets.HOST }}

        username: ${{ secrets.USER }}

        key: ${{ secrets.SSH_KEY }}

        script: |

          cd /var/www/laravel-app

          git pull origin main

          docker-compose down

          docker-compose up -d --build


Use GitHub Secrets (HOST, USER, SSH_KEY) to secure sensitive deployment credentials.


Step 3: Testing and Validation

After each push:

  • GitHub Actions installs dependencies and runs Laravel tests

  • If successful, it automatically deploys your latest changes to the server using SSH and Docker Compose

You’ll instantly receive feedback in your GitHub PR or push logs, enabling quick rollbacks and version control.


Best Practices

  • Use .env files specific to your environments (.env.staging, .env.production)

  • Use php artisan config:cache to speed up configuration loading

  • Enable caching in Composer and GitHub Actions for faster build times

  • Set up Nginx logs and error tracking

  • Enable database migrations in the pipeline when necessary


Conclusion

With Docker, Nginx, and GitHub Actions, you can confidently build and deploy Laravel apps in a repeatable, automated, and scalable manner. Whether running a side project or managing a production app, adopting CI/CD will dramatically improve your workflow and app stability.


Comments

YouTube Channel

Follow us on X