• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Orchestrating Microservices with Kubernetes: A Deep Dive into Scaling Laravel Applications with Docker

Orchestrating Microservices with Kubernetes: A Deep Dive into Scaling Laravel Applications with Docker

Containerizing Laravel: The Dockerfile Foundation

Before orchestrating, we must containerize. A robust Dockerfile is the bedrock of a scalable Laravel application on Kubernetes. This example targets a production-ready setup, minimizing image size and optimizing for security and performance.

We’ll leverage a multi-stage build. The first stage compiles assets and dependencies, while the second stage copies only the necessary artifacts to a lean runtime image. This significantly reduces the final image size, leading to faster deployments and reduced storage costs.

# Stage 1: Build dependencies and assets
FROM php:8.2-fpm-alpine AS builder

# Install system dependencies
RUN apk add --no-cache \
    git \
    zip \
    unzip \
    icu-dev \
    libzip-dev \
    libpng-dev \
    jpeg-dev \
    freetype-dev \
    imagemagick-dev \
    nodejs \
    npm \
    supervisor \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) zip

# Set working directory
WORKDIR /var/www/html

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

# Copy application files
COPY . .

# Install Composer dependencies
RUN composer install --no-dev --optimize-autoloader --no-interaction

# Install Node.js dependencies and build assets
RUN npm install && npm run build

# Clean up development dependencies and cache
RUN rm -rf node_modules vendor/ && composer install --no-dev --optimize-autoloader --no-interaction --no-cache

# Stage 2: Production runtime
FROM php:8.2-fpm-alpine

# Install system dependencies for runtime
RUN apk add --no-cache \
    icu \
    libzip \
    libpng \
    jpeg \
    freetype \
    imagemagick \
    supervisor \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) zip

# Copy compiled assets and dependencies from builder stage
COPY --from=builder /var/www/html/vendor ./vendor
COPY --from=builder /var/www/html/public/build ./public/build
COPY --from=builder /var/www/html/storage ./storage
COPY --from=builder /var/www/html/bootstrap/cache ./bootstrap/cache

# Copy application code (excluding dev files)
COPY . .

# Ensure correct permissions for storage and bootstrap/cache
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

# Copy supervisor configuration
COPY docker/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Expose port
EXPOSE 9000

# Start supervisor
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

The supervisord.conf file is crucial for managing PHP-FPM and potentially other background processes like queues. Here’s a sample:

[supervisord]
nodaemon=true
user=root

[program:php-fpm]
command=/usr/local/sbin/php-fpm -y /usr/local/etc/php-fpm.conf -D
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:queue-worker]
command=php artisan queue:work --tries=3 --timeout=60 --memory=256
autostart=true
autorestart=true
user=www-data
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stopsignal=INT

Kubernetes Manifests: Deployment and Service

With our Docker image ready, we define Kubernetes resources. A Deployment manages our application pods, ensuring the desired number of replicas are running and handling rolling updates. A Service provides a stable network endpoint for accessing the application.

We’ll use a Deployment to manage multiple replicas of our Laravel application. This allows for horizontal scaling and high availability. The Service will expose our application internally within the cluster, and we’ll typically use an Ingress controller for external access.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-app
  labels:
    app: laravel
spec:
  replicas: 3 # Start with 3 replicas
  selector:
    matchLabels:
      app: laravel
  template:
    metadata:
      labels:
        app: laravel
    spec:
      containers:
      - name: laravel-app
        image: your-docker-registry/laravel-app:latest # Replace with your image
        ports:
        - containerPort: 9000
        env:
        - name: APP_ENV
          value: "production"
        - name: APP_KEY
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: APP_KEY
        - name: DB_HOST
          value: "mysql-service" # Assuming a MySQL service named mysql-service
        - name: DB_PORT
          value: "3306"
        - name: DB_DATABASE
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_DATABASE
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_USERNAME
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_PASSWORD
        # Add other environment variables as needed (e.g., Redis, SQS)
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        livenessProbe:
          httpGet:
            path: /healthz # A simple health check endpoint in your Laravel app
            port: 9000
          initialDelaySeconds: 15
          periodSeconds: 20
        readinessProbe:
          httpGet:
            path: /readyz # A readiness check endpoint
            port: 9000
          initialDelaySeconds: 5
          periodSeconds: 10
      # Define volumes for persistent storage if needed (e.g., for logs, uploads)
      # volumes:
      # - name: shared-storage
      #   emptyDir: {}
apiVersion: v1
kind: Service
metadata:
  name: laravel-app-service
spec:
  selector:
    app: laravel
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9000 # Port PHP-FPM is listening on inside the container
  type: ClusterIP # Use ClusterIP for internal access, Ingress for external

We also need a Secret to securely store sensitive information like the APP_KEY and database credentials. This should be created separately using kubectl create secret or managed by a secrets management tool.

kubectl create secret generic laravel-secrets \
  --from-literal=APP_KEY='your_laravel_app_key_here' \
  --from-literal=DB_DATABASE='your_db_name' \
  --from-literal=DB_USERNAME='your_db_user' \
  --from-literal=DB_PASSWORD='your_db_password'

Scaling Strategies: Horizontal Pod Autoscaler (HPA)

To dynamically scale our Laravel application based on load, we employ the Horizontal Pod Autoscaler (HPA). The HPA automatically adjusts the number of pods in a deployment based on observed metrics like CPU utilization or custom metrics.

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: laravel-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: laravel-app
  minReplicas: 2 # Minimum number of pods
  maxReplicas: 10 # Maximum number of pods
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70 # Scale up when CPU utilization reaches 70%
  # - type: Resource
  #   resource:
  #     name: memory
  #     target:
  #       type: Utilization
  #       averageUtilization: 80 # Example for memory scaling
  # - type: Pods # Example for scaling based on number of pods (less common for web apps)
  #   pods:
  #     metric:
  #       name: http_requests_per_second
  #     target:
  #       type: AverageValue
  #       averageValue: 1000 # Scale up if average requests per pod exceed 1000

For custom metrics (like requests per second), you’ll need a metrics server integration (e.g., Prometheus Adapter) and potentially an application-level metrics exporter.

Database and Cache Scaling Considerations

While Kubernetes excels at scaling stateless applications like our Laravel web servers, stateful components require separate strategies. For databases (e.g., MySQL, PostgreSQL), consider managed database services (AWS RDS, Google Cloud SQL) or Kubernetes operators like the Percona Operator for MySQL.

For caching (e.g., Redis, Memcached), a managed Redis service or a Redis Cluster deployed via an operator is recommended. If deploying Redis within Kubernetes, ensure you use a StatefulSet for stable network identities and persistent storage.

# Example of a basic Redis deployment using a StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
spec:
  serviceName: "redis-headless"
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:6.2-alpine
        ports:
        - containerPort: 6379
          name: redis
        command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
        volumeMounts:
        - name: redis-config-volume
          mountPath: /usr/local/etc/redis
        - name: redis-data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
  name: redis-headless
spec:
  selector:
    app: redis
  ports:
    - port: 6379
      targetPort: 6379
  clusterIP: None # Headless service for StatefulSet

In your Laravel application’s configuration (e.g., config/database.php and config/cache.php), you would then point to the Kubernetes service name for Redis, such as redis-headless.your-namespace.svc.cluster.local.

Queue Workers and Background Jobs

Laravel’s queue workers are prime candidates for separate deployments. This allows them to scale independently of the web application and be configured with different resource limits. We can use a Deployment for queue workers, similar to the web app, but with a focus on long-running processes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: laravel-queue-worker
  labels:
    app: laravel-queue
spec:
  replicas: 2 # Start with 2 worker pods
  selector:
    matchLabels:
      app: laravel-queue
  template:
    metadata:
      labels:
        app: laravel-queue
    spec:
      containers:
      - name: laravel-queue-worker
        image: your-docker-registry/laravel-app:latest # Use the same app image
        command: ["php", "artisan", "queue:work", "--tries=3", "--timeout=60", "--memory=256"]
        env:
        - name: APP_ENV
          value: "production"
        - name: APP_KEY
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: APP_KEY
        - name: DB_HOST
          value: "mysql-service"
        - name: DB_PORT
          value: "3306"
        - name: DB_DATABASE
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_DATABASE
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_USERNAME
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: laravel-secrets
              key: DB_PASSWORD
        # Add other environment variables as needed
        resources:
          requests:
            cpu: "200m"
            memory: "256Mi"
          limits:
            cpu: "1000m"
            memory: "1024Mi"
      # Consider setting a higher restart policy for workers if appropriate
      # restartPolicy: OnFailure

You can also implement an HPA for the queue workers based on queue length or other relevant metrics. This often requires integrating with a message queue system like Redis or SQS and exposing metrics about the queue size.

Monitoring and Logging

Effective monitoring and logging are paramount in a microservices architecture. For Kubernetes, consider a stack like Prometheus for metrics collection and Grafana for visualization. For logs, Elasticsearch, Fluentd, and Kibana (EFK stack) or Loki and Promtail are popular choices.

Ensure your Laravel application exposes relevant metrics. For example, you can use packages like laravel-prometheus-exporter to expose application-level metrics that can be scraped by Prometheus. For logs, configure Laravel’s logging to output to standard output (stdout) and standard error (stderr), which Kubernetes can then collect.

// In config/logging.php, set the default driver to 'stderr'
'default' => env('LOG_CHANNEL', 'stderr'),

// Or configure specific channels to output to stdout/stderr
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single'],
        'ignore_exceptions' => false,
    ],
    'single' => [
        'driver' => 'single',
        'path' => env('LOG_PATH', 'php://stderr'), // Direct to stderr
        'level' => env('LOG_LEVEL', 'debug'),
    ],
    // ... other channels
],

By directing logs to stdout/stderr, Fluentd or Promtail agents running on your Kubernetes nodes can easily capture and forward them to your centralized logging system.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Leveraging PHP 8.3 JIT and Swoole for Real-Time, High-Concurrency Laravel Applications: A Performance Deep Dive
  • Orchestrating Microservices with Kubernetes: A Deep Dive into Scaling Laravel Applications with Docker
  • Leveraging PHP 8.3 JIT and Vectorization for Extreme Laravel Performance: A Deep Dive into Optimizing High-Throughput Applications
  • Leveraging PHP 8.3’s JIT and Vector API for Extreme Performance Gains in Laravel Applications
  • Leveraging PHP 8.3 JIT and Vector API for Extreme Performance Gains in Laravel Applications: A Deep Dive

Categories

  • apache (1)
  • AWS (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (67)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (72)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • Performance & Security Optimization (8)
  • PHP (238)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (10)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (650)
  • SEO & Growth (492)
  • Server (118)
  • Softwares (1)
  • Ubuntu (9)
  • Uncategorized (472)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (124)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Leveraging PHP 8.3 JIT and Swoole for Real-Time, High-Concurrency Laravel Applications: A Performance Deep Dive
  • Orchestrating Microservices with Kubernetes: A Deep Dive into Scaling Laravel Applications with Docker
  • Leveraging PHP 8.3 JIT and Vectorization for Extreme Laravel Performance: A Deep Dive into Optimizing High-Throughput Applications

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (728)
  • Debugging & Troubleshooting (664)
  • Security & Compliance (650)
  • SEO & Growth (492)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala