Scaling Your Laravel App with CI/CD and Docker

Hey there! As a Laravel developer, I’ve often struggled with keeping my app’s environment consistent across development, testing, and production. Manually setting up servers was a headache, and scaling my app for more users felt daunting.

That’s when I turned to Docker and CI/CD to streamline everything. In this article, I’ll walk you through how I containerized my Laravel app with Docker and set up a CI/CD pipeline using GitHub Actions to automate deployment.

This setup makes scaling your app easier and ensures consistency.

Step-by-Step Guide to Scaling Your Laravel App with CI/CD and Docker

Scaling Your Laravel App with CI/CD and Docker

Here’s how I set up Docker for my Laravel app and integrated it with a CI/CD pipeline using GitHub Actions. This approach ensures consistent environments and automates deployment for scalability.

Step 1: Set Up Your Laravel Project

First, make sure you have a Laravel project ready and pushed to a GitHub repository. If you don’t, create one:

composer create-project laravel/laravel my-laravel-app
cd my-laravel-app
git init
git add .
git commit -m "Initial commit"
git remote add origin <your-github-repo-url>
git push -u origin main

Ensure your project has some tests (e.g., created with php artisan make:test) for the CI pipeline to validate your code.

Step 2: Install and Configure Docker

Docker creates containers that package your app and its dependencies, ensuring consistency across environments. If you don’t have Docker installed, download Docker Desktop from the official Docker website and install it.

In your Laravel project’s root, create a Dockerfile to define your app’s container:

FROM php:8.1-fpm

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    unzip

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd

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

# Set working directory
WORKDIR /var/www

# Copy project files
COPY . .

# Install Laravel dependencies
RUN composer install --no-dev --optimize-autoloader

# Set permissions
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
RUN chmod -R 775 /var/www/storage /var/www/bootstrap/cache

# Expose port
EXPOSE 9000

CMD ["php-fpm"]

Next, create a docker-compose.yml file to define services (app, web server, and database):

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: my-laravel-app
    volumes:
      - .:/var/www
    environment:
      - APP_ENV=production
      - APP_KEY=${APP_KEY}
      - DB_HOST=db
      - DB_DATABASE=laravel
      - DB_USERNAME=laravel
      - DB_PASSWORD=secret

  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www
    depends_on:
      - app

  db:
    image: mysql:8.0
    environment:
      - MYSQL_DATABASE=laravel
      - MYSQL_USER=laravel
      - MYSQL_PASSWORD=secret
      - MYSQL_ROOT_PASSWORD=secret
    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:

Create an nginx.conf file for the Nginx service:

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 $document_root$fastcgi_script_name;
    }
}

Generate an app key and update .env.example (used later in CI/CD):

php artisan key:generate --show

Add the key to .env.example as APP_KEY=your-generated-key.

Step 3: Test Docker Locally

Run your app locally to ensure everything works:

docker-compose up -d

Visit http://localhost in your browser. You should see your Laravel app. If you need to run migrations:

docker-compose exec app php artisan migrate

Stop the containers when done:

docker-compose down

Step 4: Set Up a Server for Deployment

I use an AWS EC2 instance for deployment, but any server with Docker and Docker Compose works. Set up your server:

  1. Launch an EC2 instance (e.g., Ubuntu 22.04 LTS).
  2. Install Docker and Docker Compose:
sudo apt update
sudo apt install -y docker.io docker-compose
sudo usermod -aG docker ubuntu
  1. Set up SSH access by adding your public key to ~/.ssh/authorized_keys.

Step 5: Configure GitHub Actions for CI/CD

Create a file at .github/workflows/ci-cd-docker.yml:

name: Deploy Laravel with Docker

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Build Docker image
        run: docker build -t my-laravel-app .

      - name: Save Docker image
        run: docker save my-laravel-app | gzip > my-laravel-app.tar.gz

      - name: Copy image to server
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          source: "my-laravel-app.tar.gz"
          target: "/home/ubuntu"

      - name: Deploy to server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /home/ubuntu
            docker load < my-laravel-app.tar.gz
            docker-compose -f /home/ubuntu/docker-compose.yml up -d
            docker-compose exec app php artisan migrate --force
            docker-compose exec app php artisan config:cache
            docker-compose exec app php artisan route:cache

Copy docker-compose.yml and nginx.conf to your server’s /home/ubuntu directory manually or include them in the repository.

Step 6: Add GitHub Secrets

In your GitHub repository (Settings > Secrets and variables > Actions), add:

  • SERVER_IP: Your server’s public IP.
  • SSH_USER: The SSH user (e.g., ubuntu).
  • SSH_KEY: Your server’s private SSH key.

Step 7: Test the Pipeline

Push a change to your main branch:

git add .
git commit -m "Test Docker CI/CD"
git push origin main

Check the Actions tab in your GitHub repository to monitor the workflow. It builds the Docker image, transfers it to your server, and deploys it.

Step 8: Scale Your App

To handle more traffic, scale your Docker containers:

docker-compose up -d --scale app=3

Use a load balancer (e.g., AWS ALB) to distribute traffic across containers. For larger-scale apps, consider Kubernetes or AWS ECS.

Conclusion

Using Docker and GitHub Actions to scale my Laravel app has been a lifesaver. Docker ensures my app runs consistently across environments, and the CI/CD pipeline automates deployments, making scaling effortless. Whether you’re handling a few users or thousands, this setup is reliable and beginner-friendly.

Frequently Asked Questions

Q: Why use Docker with Laravel?
A: Docker ensures consistent environments across development, testing, and production, reducing “it works on my machine” issues.

Q: Can I use other CI/CD tools with Docker?
A: Yes, tools like Jenkins or GitLab CI/CD work well with Docker, but GitHub Actions is beginner-friendly and free.

Q: How do I scale my Laravel app further?
A: Use multiple containers (docker-compose --scale), a load balancer, or a container orchestrator like Kubernetes for larger-scale apps.

Q: What if my Docker deployment fails?
A: Check GitHub Actions logs for errors. Common issues include incorrect SSH keys, missing dependencies, or misconfigured docker-compose.yml.

Q: Do I need AWS for this setup?
A: No, any server with Docker works, but AWS EC2 is popular for its scalability and reliability.


You might also like :

techsolutionstuff

Techsolutionstuff | The Complete Guide

I'm a software engineer and the founder of techsolutionstuff.com. Hailing from India, I craft articles, tutorials, tricks, and tips to aid developers. Explore Laravel, PHP, MySQL, jQuery, Bootstrap, Node.js, Vue.js, and AngularJS in our tech stack.

RECOMMENDED POSTS

FEATURE POSTS