CI/CD with Docker and GitHub Actions: From Push to Production

Automate Laravel deployment pipeline using Docker and GitHub Actions for fast, reliable releases. This guide covers containerised workflows, testing strategies, and zero-downtime production deployments—from code push to live deployment.

CI/CD with Docker and GitHub Actions: From Push to Production for Laravel Developers

Modern web development demands speed, consistency, and automation — and that's where CI/CD (Continuous Integration and Continuous Deployment) comes in. If you're tired of manual deployments, broken production setups, or environment mismatches, it's time to embrace a workflow that truly works.

This guide will walk you through building a complete CI/CD pipeline using Docker and GitHub Actions, specifically tailored for Laravel developers. From pushing code to GitHub to seeing your app live in production—fully automated—you'll learn exactly how it works, step by step.


Organize Your Project: The Folder Structure

A well-organized project structure is crucial. It separates your Laravel code from infrastructure and CI/CD configurations, making your application easier to scale and manage across different environments.

your-project/
├── app/
├── docker/
│   ├── nginx/
│   └── php/
├── docker-compose.yml
└── .github/
    └── workflows/
        └── deploy.yml

Why Docker with Laravel?

Docker ensures your application runs consistently across all environments: local development, staging, and production. You'll no longer have to worry about version mismatches, missing PHP extensions, or server misconfigurations.

Here's an example docker-compose.yml that defines Laravel's essential services:

version: '3.8'

services:
  app:
    build: ./docker/php
    volumes:
      - ./app:/var/www/html
    depends_on:
      - db

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

  db:
    image: mariadb:10.6
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel

In this setup, each service (PHP, NGINX, and MariaDB) runs in its own isolated container. Your Laravel application (app/) is mounted into both the app (PHP-FPM) and web (NGINX) services, allowing seamless interaction.


Setting Up GitHub Actions for CI/CD

GitHub Actions allows you to automate your entire deployment pipeline every time you push code to your repository. This means fewer manual steps and more reliable deployments.

Here's a basic .github/workflows/deploy.yml file to get you started:

name: Deploy Laravel App

on:
  push:
    branches:
      - main # This workflow triggers on pushes to the 'main' branch

jobs:
  deploy:
    runs-on: ubuntu-latest # The job will run on a fresh Ubuntu virtual machine

    steps:
    - name: Checkout code
      uses: actions/checkout@v3 # Fetches your repository's code

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2 # Essential for building multi-platform Docker images

    - name: Build and bring up Docker containers locally
      run: |
        docker build -t laravel-app ./docker/php # Builds your PHP application image
        docker-compose -f docker-compose.yml up -d --build # Starts your services defined in docker-compose.yml

    - name: Deploy to Remote Server
      uses: appleboy/ssh-action@v1 # A popular action for connecting to remote servers via SSH
      with:
        host: ${{ secrets.SERVER_IP }} # Your server's IP address
        username: ${{ secrets.SSH_USER }} # SSH username on your server
        key: ${{ secrets.SSH_KEY }} # Your private SSH key for authentication
        script: |
          cd /var/www/your-project # Navigate to your project directory on the server
          git pull origin main # Pull the latest code from GitHub
          docker-compose down # Stop and remove existing Docker containers
          docker-compose up -d --build # Rebuild and start new Docker containers

This pipeline efficiently handles the following:

  • Triggers on push to the main branch, initiating the deployment process automatically.
  • Builds Docker images locally within the GitHub Actions runner.
  • Connects to your remote server via SSH using securely stored credentials.
  • Pulls the latest code to your server and restarts Docker containers, ensuring your live application is always up-to-date.

Securing Secrets in GitHub

Never hardcode sensitive information directly into your workflow files. Instead, leverage GitHub's built-in secrets management system.

Navigate to your repository settings:
Settings > Secrets and variables > Actions

Add the following repository secrets:

  • SERVER_IP: The IP address of your production server.
  • SSH_USER: The SSH username for connecting to your server.
  • SSH_KEY: Your private SSH key (ensure it's properly formatted with -----BEGIN OPENSSH PRIVATE KEY----- and -----END OPENSSH PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- headers and footers).

These values will be securely injected into your workflow at runtime, providing a robust and safe deployment mechanism.


Benefits of This Setup

Adopting this CI/CD pipeline offers significant advantages for Laravel developers:

  • Automated Deployments: Save considerable time and drastically reduce the risk of human error by eliminating manual deployment steps.
  • Consistency Across Environments: Docker guarantees your application behaves identically across local development, staging, and production.
  • Visibility and Control: GitHub Actions provides a clear, step-by-step overview of each deployment, making it easy to monitor progress and troubleshoot issues.
  • Easier Rollbacks: If something goes wrong, rolling back to a previous stable version is much faster and simpler.

Final Thoughts

Setting up CI/CD with Docker and GitHub Actions might require a small upfront investment of time, but the payoff is immense. Once in place, every push to your GitHub repository can instantly trigger testing, building, and deployment to production. Your deployments become repeatable, reliable, and stress-free.

This guide lays the groundwork for a highly scalable and robust Laravel deployment pipeline. You can further extend it with advanced features like:

  • Automated testing: Integrate unit, feature, and end-to-end tests into your pipeline.
  • Staging environments: Deploy to a staging server for final testing before production.
  • Notifications: Set up Slack or email notifications for deployment status updates.
  • Advanced rollback strategies: Implement more sophisticated rollback mechanisms.

If you're serious about modern Laravel development, embracing CI/CD is undoubtedly one of the smartest moves you can make to streamline your workflow and deliver applications faster and more reliably.