Deploying Laravel Applications with Docker and Kubernetes

Containerizing Laravel with Docker and orchestrating with Kubernetes gives you consistent environments, easy scaling, and reliable deployments. This is the exact setup I've used in production for European-standard payroll and SaaS applications.

Laravel Dockerfile

A multi-stage Dockerfile keeps the final image lean:

FROM php:8.2-fpm-alpine AS base RUN apk add --no-cache git curl libpng-dev oniguruma-dev libxml2-dev zip unzip RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www COPY . . RUN composer install --no-dev --optimize-autoloader RUN chown -R www-data:www-data /var/www EXPOSE 9000 CMD ["php-fpm"]

Docker Compose for Local Development

version: '3.8' services: app: build: . container_name: laravel_app volumes: - .:/var/www networks: - laravel nginx: image: nginx:alpine container_name: laravel_nginx ports: - "8000:80" volumes: - .:/var/www - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - app networks: - laravel mysql: image: mysql:8.0 container_name: laravel_mysql environment: MYSQL_DATABASE: laravel MYSQL_ROOT_PASSWORD: password ports: - "3306:3306" networks: - laravel networks: laravel: driver: bridge

Kubernetes Deployment

Deployment Config

apiVersion: apps/v1 kind: Deployment metadata: name: laravel-app spec: replicas: 3 selector: matchLabels: app: laravel-app template: metadata: labels: app: laravel-app spec: containers: - name: laravel-app image: your-registry/laravel-app:latest ports: - containerPort: 9000 env: - name: DB_HOST value: "mysql-service" resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m"

Service Config

apiVersion: v1 kind: Service metadata: name: laravel-service spec: selector: app: laravel-app ports: - port: 80 targetPort: 9000 type: LoadBalancer

CI/CD with GitHub Actions

name: Deploy to Kubernetes on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build Docker image run: docker build -t laravel-app:${{ github.sha }} . - name: Push to registry run: | docker tag laravel-app:${{ github.sha }} your-registry/laravel-app:${{ github.sha }} docker push your-registry/laravel-app:${{ github.sha }} - name: Deploy to Kubernetes run: kubectl set image deployment/laravel-app laravel-app=your-registry/laravel-app:${{ github.sha }}

Horizontal Pod Autoscaling

apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: laravel-app-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: laravel-app minReplicas: 3 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 80
Production tip: Always use specific image tags (like the git SHA) instead of latest. It makes rollbacks trivial and deployments fully reproducible.

Conclusion

Start with Docker Compose for local development to ensure environment consistency across your team. When you're ready for production, Kubernetes gives you autoscaling, zero-downtime deployments, and easy rollbacks. The GitHub Actions pipeline automates the whole process on every push to main.

About the Author

Kamruzzaman Polash — Software Engineer specialising in Laravel, REST APIs, and scalable backend systems. 10+ projects delivered for clients worldwide.