Laravel CI/CD Pipeline Architectures via GitLab

The implementation of Continuous Integration and Continuous Deployment (CI/CD) for Laravel applications represents a critical shift from manual server management to automated software delivery. In a modern development lifecycle, the objective is to ensure that every code push is systematically validated through automated testing and quality gates before reaching a production environment. This process eliminates the "it works on my machine" syndrome by utilizing containerization and orchestrated pipelines. By integrating GitLab CI/CD, developers can create a seamless bridge between the version control system and the target infrastructure, whether that infrastructure is a lightweight Kubernetes cluster, a traditional Ubuntu server, or a managed cloud environment like AWS Elastic Beanstalk.

The primary goal of these architectures is to automate the building, testing, and deployment phases. When a developer pushes code to a branch, GitLab CI/CD triggers a series of jobs defined in a configuration file. This ensures that unit tests are executed and code quality is verified using tools like PHP CodeSniffer. If these stages pass, the application is packaged into a Docker image and deployed to the server. This automation reduces human error and ensures that updates are delivered smoothly without breaking the live application.

Infrastructure and Technology Stack Configurations

The choice of technology stack for a Laravel CI/CD pipeline significantly impacts the scalability and cost-efficiency of the deployment. Depending on the organizational needs, different combinations of tools are employed to achieve the desired deployment frequency and reliability.

Kubernetes and Cloud-Native Stack

For high-availability environments, a cloud-native stack involving Kubernetes is often preferred. This approach leverages the orchestration capabilities of K3s, a lightweight distribution of Kubernetes, which allows for efficient resource utilization even on low-cost hardware.

Component Technology Purpose
Application Framework Laravel Core PHP web framework
Containerization Docker Environment isolation and packaging
Repository & CI/CD GitLab Version control and pipeline orchestration
Container Registry GitLab Container Registry Storage for built Docker images
Orchestration K3s (Kubernetes) Container management and scaling
Deployment Automation ArgoCD GitOps-based continuous delivery
Infrastructure Hetzner VPS Hosting server (Example: 4GB RAM / 2 CPU cores)
Operating System Debian Base OS for the server
Networking/Security Cloudflare DNS management and SSL termination
Management UI Portainer Visual container management

The use of a Hetzner server priced at approximately $5 provides a cost-effective entry point for deploying a K3s cluster. Cloudflare is integrated to handle the custom domain and provide HTTPS via SSL, which is a mandatory requirement for modern web security. Portainer and ArgoCD provide the necessary visibility into the infrastructure, allowing administrators to monitor the state of the pods and the health of the deployment without relying solely on the command line.

AWS Elastic Beanstalk Stack

An alternative approach involves utilizing AWS Elastic Beanstalk, which abstracts the underlying EC2 instances and provides a managed environment for deploying Laravel. This setup focuses on branch-based deployments, where specific actions are tied to the state of the git branch.

  • Master branch: Used for production. Deployments to this branch are typically set to manual to prevent accidental pushes from triggering a production update.
  • Staging branch: Used for final verification. If PHPUnit tests pass on this branch, the application is automatically deployed to the staging environment on Elastic Beanstalk.

This architecture requires an IAM user with Elastic Beanstalk Full Access permissions, utilizing Access and Secret Keys for authentication. The EB CLI is used to initialize the environment through the eb init command, which creates a .elasticbeanstalk folder in the project root to store environment configurations.

Containerization Strategy for Laravel

Containerizing a Laravel application ensures that the environment remains consistent across development, staging, and production. This is achieved by defining a Dockerfile that encapsulates the PHP runtime and all necessary system dependencies.

The Dockerfile Specification

A robust Docker environment for Laravel requires a base image that includes PHP and the Apache web server. The following configuration illustrates the professional standard for a Laravel Docker image:

```dockerfile

Base image with PHP and Apache

FROM php:8-apache

Install system dependencies and PHP extensions

RUN apt-get update && apt-get install -y \
curl \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
libzip-dev \
zip \
unzip \
supervisor \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd bcmath pdo pdo_mysql zip

Install pcov for laravel test coverage

RUN pecl install pcov && \
docker-php-ext-enable pcov

Enable Apache modules

RUN a2enmod rewrite

Set working directory

WORKDIR /var/www/html

Copy existing application directory contents

COPY ./src .

Install Composer

COPY --from=composer /usr/bin/composer /usr/bin/composer

Copy custom Apache virtual host configuration

COPY conf/apache/000-default.conf /etc/apache2/sites-available/000-default.conf

Expose port 80

EXPOSE 80

Start Apache in the foreground

CMD ["apache2-foreground"]
```

The impact of this configuration is twofold: first, it ensures that all required PHP extensions like gd, bcmath, pdo_mysql, and zip are present, preventing runtime errors during the execution of Laravel's core functions. Second, the installation of pcov allows the CI/CD pipeline to generate accurate test coverage reports, which is essential for maintaining high software quality.

Project Directory Structure

A well-organized project structure is vital for the CI/CD pipeline to locate the source code and configuration files. The standard layout for a containerized Laravel project is as follows:

  • laravel-app/
    • app/
    • artisan
    • bootstrap/
    • components.json
    • composer.json
    • composer.lock
    • config/
    • database/
    • eslint.config.js
    • node_modules/
    • package.json
    • package-lock.json
    • phpunit.xml
    • public/
    • resources/
    • routes/
    • storage/
    • tests/
    • tsconfig.json
    • vendor/
    • vite.config.ts
  • docker/
    • compose.yaml

The docker/ folder separates infrastructure concerns from application logic, while the laravel-app/ folder contains the entire framework and custom code.

GitLab CI/CD Pipeline Configuration

The heart of the automation process is the .gitlab-ci.yml file. This file defines the stages, jobs, and environment variables required to move code from a commit to a live server.

Pipeline Stages and Environment Variables

The pipeline is divided into four primary stages: build, test, quality, and deploy. To facilitate these, a default image of docker:latest is used, with docker:dind (Docker-in-Docker) as a service to allow the building of images within the pipeline.

The following configuration snippet defines the environment and the build stage:

```yaml
default:
image: docker:latest
services:
- docker:dind
beforescript:
- echo "$CI
REGISTRYPASSWORD" | docker login -u $CIREGISTRYUSER $CIREGISTRY --password-stdin

variables:
DOCKERDRIVER: overlay2
MYSQL
DATABASE: laravel
MYSQLROOTPASSWORD: secret
MYSQLUSER: laravel
MYSQL
PASSWORD: secret
TESTDBHOST: mysql
TESTDBPORT: 3306
IMAGE: $CIREGISTRYIMAGE/app:latest

stages:
- build
- test
- quality
- deploy

build:
stage: build
script:
- docker pull $IMAGE || true
- docker run --rm -v $PWD/src:/app composer install --optimize-autoloader --prefer-dist --no-scripts
- docker build -f php.dockerfile --build-arg BUILDKITINLINECACHE=1 --cache-from $IMAGE --tag $CIREGISTRYIMAGE/app:$CICOMMITSHA --tag $IMAGE .
- docker push $IMAGE
- docker push $CIREGISTRYIMAGE/app:$CICOMMITSHA
only:
- main
cache:
key: ${CICOMMITREF_SLUG}-composer
paths:
- src/vendor/
policy: push
```

The build stage performs several critical actions. First, it attempts to pull the existing image to use as a cache, which significantly speeds up subsequent builds. Second, it runs composer install within a temporary container to resolve dependencies. Third, it builds the final image using the php.dockerfile and tags it with both the commit SHA (for traceability) and the latest tag. Finally, the image is pushed to the GitLab Container Registry.

Testing and Quality Assurance

Once the build is complete, the pipeline moves to the test and quality stages. This ensures that no regression bugs are introduced into the production environment.

  • Unit Testing: The pipeline runs tests using either Pest or PHPUnit. A special .env.ci file is utilized during this stage to provide the necessary database credentials and application settings specifically for the testing environment.
  • Code Quality: PHP CodeSniffer (PHP-CS) is integrated to enforce coding standards. This step prevents the codebase from becoming inconsistent, which is vital for long-term maintainability in team environments.

Advanced Deployment Strategies

Depending on the target environment, the deployment mechanism varies from direct server pushes to sophisticated GitOps workflows.

Deployment to Ubuntu Servers

In a traditional setup, the application is deployed to an Ubuntu server with Docker installed. The pipeline handles the pulling of the latest image from the registry and the restarting of the containers. This is often managed via Docker Compose to ensure that the application and its dependencies (like MySQL) are started in the correct order.

AWS Elastic Beanstalk and .ebextensions

For AWS deployments, the process leverages the EB CLI. To manage server-side configurations, the .ebextensions folder is used. This folder contains YAML files that instruct AWS to run specific commands during the deployment lifecycle.

To set up these extensions, the following command can be used to import a proven configuration:

bash svn export https://github.com/mjsarfatti/laravel-eb-gitlab-ci/trunk/.ebextensions

These extensions handle critical tasks such as:
- Running composer install to ensure dependencies are present.
- Executing php artisan migrate to update the database schema.
- Configuring Apache to serve the application from the /public folder.
- Implementing HTTP to HTTPS redirection to ensure secure traffic.

GitOps with ArgoCD and K3s

In the most advanced setup, ArgoCD is used to implement a GitOps workflow. Instead of the CI pipeline pushing code to the server, ArgoCD monitors the Git repository (or a separate config repo) and "pulls" the state of the cluster to match the desired state defined in the manifests.

This setup provides several advantages:
- Automatic Synchronization: Any change to the Kubernetes manifests in Git is automatically reflected in the K3s cluster.
- Visibility: The ArgoCD dashboard provides a visual representation of the application's health and deployment status.
- Rollback Capability: Reverting a deployment is as simple as reverting a commit in Git.

Comprehensive Summary of CI/CD Workflows

The implementation of these pipelines varies based on the desired level of automation and the underlying infrastructure.

  • For Rapid Prototyping: Use GitLab CI with a simple Docker Compose setup on an Ubuntu server.
  • For Enterprise Scaling: Use GitLab CI, K3s, and ArgoCD for a full GitOps experience.
  • For Managed Cloud: Use GitLab CI combined with AWS Elastic Beanstalk and .ebextensions.

The impact of these workflows is a drastic reduction in the time between "code complete" and "production live." By enforcing a strict sequence of build, test, quality, and deploy, organizations can maintain a high velocity of feature delivery without sacrificing system stability.

Conclusion

The architectural transition to a fully automated Laravel CI/CD pipeline via GitLab is not merely a technical upgrade but a strategic necessity for modern software engineering. By integrating Docker for environmental consistency, K3s or AWS Elastic Beanstalk for scalable orchestration, and GitLab CI/CD for process automation, developers can achieve a state of continuous delivery. The use of specialized tools such as ArgoCD for GitOps and PHP CodeSniffer for quality assurance ensures that the deployment process is transparent, repeatable, and resilient. The integration of a dedicated testing environment using .env.ci and the automation of database migrations via .ebextensions further solidifies the reliability of the deployment. Ultimately, these systems move the burden of deployment from manual, error-prone scripts to a deterministic, code-driven pipeline, allowing developers to focus on building features rather than managing infrastructure.

Sources

  1. Build with Code - Laravel CI/CD
  2. 9ovind - Laravel Full CI/CD Setup
  3. Dev.to - Deploy Laravel to AWS Beanstalk with GitLab CI

Related Posts