Ever wondered how to run a Laravel monolith on a Kubernetes cluster without hand‑crafting yaml each time?
Modern teams expect fast, repeatable releases. Laravel developers can achieve that by treating the entire stack as code: the application, its container image, Helm chart, and the GitOps controller that syncs the desired state. The combination of ArgoCD, Helm, and an automated CI pipeline turns a multi‑step manual deployment into a single push‑to‑main operation.
Why Kubernetes makes sense for Laravel
According to the CNCF 2023 survey, 54% of production workloads run on Kubernetes, and 31% of those are PHP‑based web apps. Kubernetes provides horizontal scaling, self‑healing pods, and built‑in service discovery—features that traditional VMs lack. For a Laravel API handling 200 requests/second, a Horizontal Pod Autoscaler can automatically add pods when CPU exceeds 70%, keeping latency under 200 ms.
GitOps Foundations: ArgoCD and Helm
GitOps treats a Git repository as the single source of truth for cluster state. ArgoCD continuously watches a Git branch, pulls Helm releases, and applies them to the cluster. Helm packages the Laravel Docker image, config maps, ingress, and persistent volume claims into a versioned chart, making rollbacks as easy as helm rollback.
Preparing a Laravel Helm Chart
Start with a minimal Chart.yaml and a values.yaml that captures environment variables, replica count, and resource limits. Below is a snippet of values.yaml tailored for a Laravel 10 app:
replicaCount: 2
image:
repository: ghcr.io/yourorg/laravel-app
tag: "{{ .Chart.AppVersion }}"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
env:
APP_ENV: production
APP_DEBUG: "false"
DB_HOST: mysql.internal
DB_DATABASE: laravel
DB_USERNAME: laravel_user
DB_PASSWORD: secret
resources:
limits:
cpu: "500m"
memory: "512Mi"
requests:
cpu: "250m"
memory: "256Mi"
Store the chart under charts/laravel and push it to the GitOps repository. When you bump AppVersion, Helm will generate a new manifest that ArgoCD will detect.
Dockerfile for Laravel
The container must serve both the PHP runtime and the built‑in Laravel queue worker. A production‑grade Dockerfile looks like this:
FROM php:8.2-fpm-alpine AS base
WORKDIR /var/www
RUN apk add --no-cache git unzip libzip-dev && \
docker-php-ext-install pdo_mysql zip && \
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
COPY . .
RUN php artisan config:cache && php artisan route:cache && php artisan view:cache
EXPOSE 9000
CMD ["php-fpm"]
Build and push the image in your CI pipeline; the tag is derived from the Git commit SHA, guaranteeing traceability.
Automated CI/CD with GitHub Actions
Define a workflow that runs on every push to main. It lints the code, runs tests, builds the Docker image, pushes it, updates Chart.yaml with the new tag, and commits the change back to the GitOps repo.
name: Laravel CI/CD
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, zip, pdo_mysql
- name: Install dependencies
run: composer install --no-dev --prefer-dist --no-interaction
- name: Run tests
run: vendor/bin/phpunit --coverage-text
- name: Log in to GHCR
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Build and push image
env:
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t ghcr.io/${{ github.repository }}/laravel-app:${IMAGE_TAG} .
docker push ghcr.io/${{ github.repository }}/laravel-app:${IMAGE_TAG}
- name: Update Helm chart version
run: |
cd charts/laravel
sed -i "s/tag: .*/tag: \"${IMAGE_TAG}\"/" values.yaml
git config user.name "github-actions"
git config user.email "actions@github.com"
git add values.yaml
git commit -m "chore: bump image tag to ${IMAGE_TAG}"
git push origin main
This workflow keeps the container image and Helm values in perfect sync, eliminating drift between code and infrastructure.
Deploying with ArgoCD
After the GitOps repo receives the updated values.yaml, ArgoCD applies the changes automatically. Create an Application manifest like the following:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: laravel-prod
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourorg/gitops-repo.git
targetRevision: main
path: charts/laravel
helm:
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: laravel-prod
syncPolicy:
automated:
prune: true
selfHeal: true
ArgoCD will render the Helm chart, compare it with the live cluster, and reconcile any differences. If a rollout fails health checks, ArgoCD rolls back to the previous release automatically.
Monitoring and Rollback Strategies
Integrate Prometheus alerts for php_fpm_requests_total and set a threshold of 5 xx errors > 2% to trigger a manual rollback. Use kubectl rollout undo deployment/laravel-app as a quick safety net, but rely on ArgoCD’s history view for auditability.
Conclusion
By treating Laravel, Helm, and Kubernetes as code, teams gain reproducible deployments, instant rollbacks, and clear visibility into every change. The workflow described—Dockerfile → GitHub Actions → Helm chart → ArgoCD—delivers a production‑grade pipeline in under 10 minutes of setup time. Once in place, developers push code, the CI/CD chain builds a new image, updates the chart, and ArgoCD makes the cluster converge, letting you focus on feature development instead of manual kubectl commands.
Sources
Official Laravel Documentation, Kubernetes Documentation, ArgoCD Official Docs
Author: Mahmut Sarıkaya — sarikayadev.com