• 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 » Beyond the Basics: Advanced Docker Orchestration for High-Availability Laravel Applications on AWS

Beyond the Basics: Advanced Docker Orchestration for High-Availability Laravel Applications on AWS

Establishing a Robust Docker Swarm for Laravel HA on AWS

Moving beyond single-instance Docker deployments, this guide details the architecture and implementation of a highly available (HA) Laravel application orchestrated with Docker Swarm on Amazon Web Services (AWS). We’ll focus on critical components like multi-AZ database replication, load balancing, and automated service scaling, ensuring resilience and performance under load.

AWS Infrastructure Blueprint

A production-ready HA setup necessitates a multi-Availability Zone (AZ) deployment. Our core AWS components will include:

  • VPC: A custom VPC with public and private subnets spanning at least two AZs.
  • EC2 Instances: A cluster of EC2 instances (e.g., t3.medium or m5.large, depending on load) configured as Docker Swarm managers and workers. These should reside in private subnets.
  • RDS Aurora Cluster: A highly available Aurora PostgreSQL or MySQL cluster configured for multi-AZ replication. This is non-negotiable for data durability.
  • Elastic Load Balancer (ELB): An Application Load Balancer (ALB) to distribute incoming HTTP/S traffic across our Swarm services.
  • Security Groups: Carefully configured security groups to control ingress and egress traffic between components (e.g., allowing traffic from ALB to Swarm nodes on port 80/443, Swarm nodes to RDS on the database port, and inter-Swarm node communication).
  • Route 53: For DNS management, pointing to the ALB.

Docker Swarm Initialization and Node Configuration

We’ll start by initializing the Docker Swarm on our designated manager node. Subsequent nodes will join as workers.

Manager Node Initialization

SSH into your chosen manager EC2 instance. Ensure Docker is installed and running. Then, execute the initialization command:

sudo docker swarm init --advertise-addr <MANAGER_NODE_PRIVATE_IP>

This command will output a `docker swarm join` command with a token. Save this token; it’s crucial for adding worker nodes.

Worker Node Joining

On each worker EC2 instance, run the join command obtained from the manager:

sudo docker swarm join --token <SWARM_JOIN_TOKEN> <MANAGER_NODE_PRIVATE_IP>:2377

Verify that all nodes have joined the swarm by running the following command on the manager node:

sudo docker node ls

Laravel Application Dockerfile and Compose Configuration

A well-structured Dockerfile is key. We’ll use an official PHP-FPM image and install necessary extensions. For production, consider multi-stage builds to reduce image size.

Dockerfile Example

# Use an official PHP image with FPM
FROM php:8.2-fpm

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install pdo pdo_mysql zip exif && \
    pecl install redis && docker-php-ext-enable redis && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# Set working directory
WORKDIR /var/www/html

# Copy application files
COPY . /var/www/html

# Install Composer dependencies
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer install --no-dev --optimize-autoloader

# Permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
RUN chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache

# Expose port
EXPOSE 9000

# Default command
CMD ["php-fpm"]

Docker Compose for Swarm Services

We’ll define our services (web, app, worker) using a docker-compose.yml file. This file will be deployed to the Swarm.

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - web-data:/var/www/html # Mount point for static assets if any
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
    networks:
      - app-network
    deploy:
      replicas: 3 # Scale Nginx instances
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker # Deploy on worker nodes
    depends_on:
      - app

  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/var/www/html # Mount for development, use volumes for production
      - php-sessions:/var/lib/php/sessions # Shared session storage
    networks:
      - app-network
    environment:
      APP_NAME: Laravel HA App
      APP_ENV: production
      APP_KEY: base64:YOUR_APP_KEY_HERE=
      APP_DEBUG: 'false'
      APP_URL: http://your-domain.com
      DB_CONNECTION: pgsql # Or mysql
      DB_HOST: <RDS_ENDPOINT>
      DB_PORT: 5432 # Or 3306
      DB_DATABASE: <DB_NAME>
      DB_USERNAME: <DB_USER>
      DB_PASSWORD: <DB_PASSWORD>
      REDIS_HOST: redis
      REDIS_PORT: 6379
    deploy:
      replicas: 5 # Scale Laravel app instances
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker
    depends_on:
      - redis
      - queue_worker

  redis:
    image: redis:alpine
    networks:
      - app-network
    deploy:
      replicas: 1 # Redis typically doesn't need many replicas for caching
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker

  queue_worker:
    build:
      context: .
      dockerfile: Dockerfile
    command: php artisan queue:work --queue=default,high --tries=3 --timeout=60
    volumes:
      - .:/var/www/html
      - php-sessions:/var/lib/php/sessions
    networks:
      - app-network
    environment:
      APP_NAME: Laravel HA App
      APP_ENV: production
      APP_KEY: base64:YOUR_APP_KEY_HERE=
      APP_DEBUG: 'false'
      APP_URL: http://your-domain.com
      DB_CONNECTION: pgsql
      DB_HOST: <RDS_ENDPOINT>
      DB_PORT: 5432
      DB_DATABASE: <DB_NAME>
      DB_USERNAME: <DB_USER>
      DB_PASSWORD: <DB_PASSWORD>
      REDIS_HOST: redis
      REDIS_PORT: 6379
    deploy:
      replicas: 3 # Scale queue workers
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker
    depends_on:
      - redis

networks:
  app-network:
    driver: overlay
    attachable: true

volumes:
  php-sessions:
    driver: local # For shared session storage across app containers on the same node
  web-data:
    driver: local

Important Notes:

  • Replace placeholders like <RDS_ENDPOINT>, <DB_NAME>, <DB_USER>, <DB_PASSWORD>, and YOUR_APP_KEY_HERE with your actual AWS RDS and Laravel application credentials.
  • The volumes section for the app service is commented out for production. In a true HA setup, you’d typically use external persistent storage (like AWS EFS) or rely on shared session drivers (like Redis or database sessions) and avoid direct file mounts for code.
  • The php-sessions volume is a local volume, meaning sessions will be shared only among containers running on the *same* Swarm node. For true session HA, configure Laravel to use Redis or database sessions.
  • The web service’s Nginx configuration (./nginx/conf.d) needs to be created and will point to the app service.

Nginx Configuration for Reverse Proxy

Create a directory named nginx in the same directory as your docker-compose.yml and add a conf.d subdirectory. Inside conf.d, create a file (e.g., app.conf) for Nginx to act as a reverse proxy to your Laravel application service.

server {
    listen 80;
    server_name your-domain.com; # Replace with your actual domain

    root /var/www/html/public;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        # Use the Docker service name for the upstream PHP-FPM
        fastcgi_pass app:9000; # 'app' is the service name in docker-compose.yml
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    location ~ /\.ht {
        deny all;
    }

    # Serve static files directly
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;
        add_header Cache-Control "public";
    }
}

Note: The fastcgi_pass app:9000; directive assumes your Laravel PHP-FPM service is named app in the docker-compose.yml. The DNS resolution for service names is handled by Docker Swarm’s internal DNS.

Deploying Services to Docker Swarm

Navigate to the directory containing your docker-compose.yml and the nginx configuration on your manager node. Then, deploy the stack:

sudo docker stack deploy -c docker-compose.yml laravel_app

You can monitor the deployment and status of your services with:

sudo docker stack services laravel_app
sudo docker stack ps laravel_app

Configuring AWS Application Load Balancer (ALB)

The ALB will be the entry point for your application. It needs to be configured to forward traffic to your Docker Swarm nodes.

Target Groups

Create a Target Group:

  • Protocol: HTTP
  • Port: 80
  • Target type: Instances
  • VPC: Select your custom VPC.
  • Health checks: Configure health checks to point to a health check endpoint in your Laravel app (e.g., /health). This endpoint should return a 200 OK status.

Load Balancer

Create an Application Load Balancer:

  • Scheme: Internet-facing
  • VPC: Select your custom VPC.
  • Mappings: Select the public subnets in your chosen AZs.
  • Listeners: Add an HTTP listener on port 80.
  • Default Action: Forward to the Target Group created above.
  • Security Groups: Ensure the ALB’s security group allows inbound traffic on port 80 from 0.0.0.0/0 (or a more restrictive CIDR) and allows outbound traffic to your Swarm nodes on port 80.

Security Group for Swarm Nodes

The security group attached to your EC2 instances (Swarm nodes) must allow:

  • Inbound traffic on port 80 from the ALB’s security group.
  • Inbound traffic on port 2377 (Swarm management), 7946 (overlay network), and 4789 (overlay network) from within your VPC.
  • Outbound traffic to your RDS instance on the database port.

Database HA with RDS Aurora

AWS RDS Aurora (PostgreSQL or MySQL compatible) inherently provides high availability by replicating data across multiple AZs within a region. Your Laravel application, configured with the RDS endpoint as its database host, will automatically connect to the primary instance. In case of a failover, RDS promotes a replica to primary, and your application will reconnect to the new primary endpoint (though a brief interruption might occur during the failover process).

Session Management for HA

Relying on local Docker volumes for sessions (as shown in the commented-out section of the docker-compose.yml) is not HA. For true high availability, configure Laravel’s session driver to use a shared backend:

  • Redis: Use the redis service defined in the docker-compose.yml. Ensure your .env file (or environment variables) points to the Redis service.
  • Database: Use your RDS Aurora instance. This adds load to your database but is a viable option.

To configure Laravel to use Redis sessions, ensure your .env file (or environment variables passed to the container) has:

SESSION_DRIVER=redis

Health Checks and Monitoring

Implement a health check endpoint in your Laravel application (e.g., routes/web.php):

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;

Route::get('/health', function () {
    try {
        // Check database connection
        DB::connection()->getPdo();
        // Check cache connection (if using Redis)
        Cache::store('redis')->get('health_check'); // Simple cache check
        Cache::store('redis')->put('health_check', 'ok', 10); // Set a value to ensure write works

        return response()->json(['status' => 'ok', 'message' => 'Application is healthy'], 200);
    } catch (\Exception $e) {
        return response()->json(['status' => 'error', 'message' => 'Application is unhealthy: ' . $e->getMessage()], 500);
    }
});

This endpoint should be configured in your ALB’s target group health checks. Additionally, leverage Docker Swarm’s built-in service health monitoring and consider integrating with external monitoring tools like Prometheus/Grafana or Datadog for comprehensive visibility into your Swarm and application performance.

Scaling and Maintenance

Docker Swarm allows for easy scaling of services:

# Scale the app service to 10 replicas
sudo docker service scale laravel_app_app=10

# Update the image for a service (e.g., after a new deployment)
sudo docker service update --image your-dockerhub-username/your-laravel-app:latest laravel_app_app

For rolling updates, Docker Swarm handles this by default when you update a service’s image. It will gradually replace old tasks with new ones, minimizing downtime. Ensure your application is designed to handle graceful shutdowns.

Conclusion

This architecture provides a solid foundation for a highly available Laravel application on AWS using Docker Swarm. By leveraging AWS managed services like RDS Aurora and ALB, combined with Docker Swarm’s orchestration capabilities, you can achieve resilience, scalability, and simplified management for your production workloads.

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

  • Beyond the Basics: Advanced Docker Orchestration for High-Availability Laravel Applications on AWS
  • Leveraging PHP 8 JIT and Laravel Octane for Sub-Second API Response Times: A Deep Dive into Performance Tuning
  • Orchestrating Microservices with Laravel Octane and AWS ECS: A Performance and Scalability Deep Dive
  • Leveraging PHP 8.3+ JIT and OpCache for Sub-Millisecond WordPress API Response Times with Laravel Octane
  • Unlocking Kubernetes Scalability: Advanced Strategies for PHP/Laravel Microservices with Redis and Traefik

Categories

  • apache (1)
  • AWS (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (57)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (53)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • Performance & Security Optimization (8)
  • PHP (187)
  • 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 (365)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (97)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Beyond the Basics: Advanced Docker Orchestration for High-Availability Laravel Applications on AWS
  • Leveraging PHP 8 JIT and Laravel Octane for Sub-Second API Response Times: A Deep Dive into Performance Tuning
  • Orchestrating Microservices with Laravel Octane and AWS ECS: A Performance and Scalability Deep Dive

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