• 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 High-Availability WordPress with Docker Swarm and AWS Load Balancing: A Deep Dive into Infrastructure as Code

Orchestrating High-Availability WordPress with Docker Swarm and AWS Load Balancing: A Deep Dive into Infrastructure as Code

Docker Swarm Service Definition for WordPress

To achieve high availability for WordPress, we’ll leverage Docker Swarm’s declarative service model. This allows us to define the desired state of our application, and Swarm will ensure it’s maintained. We’ll define separate services for the WordPress application itself, the PHP-FPM backend, and the database. For this example, we’ll use MariaDB as our database, a common and robust choice for WordPress.

The core of our Swarm deployment will be a docker-compose.yml file. This file will define our services, networks, and volumes. We’ll ensure that WordPress and PHP-FPM are configured to communicate over a shared Docker network and that persistent data is managed via named volumes.

WordPress and PHP-FPM Service Configuration

The WordPress application service will primarily serve static assets and act as a reverse proxy to the PHP-FPM service for dynamic requests. We’ll use an official Nginx image as the web server. The PHP-FPM service will handle the WordPress PHP execution. We’ll use the official PHP-FPM image, configured to listen on a specific port that Nginx can connect to.

docker-compose.yml – Services Section

Here’s a snippet of the docker-compose.yml file focusing on the WordPress and PHP-FPM services:

version: '3.8'

services:
  wordpress:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - wordpress_data:/var/www/html
      - ./nginx/conf.d:/etc/nginx/conf.d
    networks:
      - wordpress_net
    deploy:
      replicas: 3
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    depends_on:
      - php-fpm

  php-fpm:
    image: php:8.2-fpm-alpine
    volumes:
      - wordpress_data:/var/www/html
      - ./php/conf.d:/usr/local/etc/php/conf.d
    networks:
      - wordpress_net
    deploy:
      replicas: 3
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
    depends_on:
      - db

volumes:
  wordpress_data:

networks:
  wordpress_net:

Nginx Configuration for WordPress

The Nginx configuration is crucial for routing traffic correctly. It needs to serve static files directly and proxy PHP requests to the PHP-FPM service. We’ll configure Nginx to use the service name php-fpm as the upstream server, allowing Docker Swarm’s internal DNS to resolve it.

nginx/conf.d/default.conf

Create a file named default.conf within an nginx/conf.d/ directory in your project root:

server {
    listen 80;
    server_name localhost; # Or your domain name

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

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000; # Docker Swarm service name and port
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }

    # Caching for static assets
    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml|txt)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

Database Service Configuration (MariaDB)

For the database, we’ll use a MariaDB image. It’s essential to configure persistent storage for the database data. We’ll also set environment variables for root password and database creation. For production, consider using AWS RDS or a managed database service instead of self-hosting within Swarm for better reliability and scalability.

docker-compose.yml – Database Section

  db:
    image: mariadb:10.6
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-supersecretrootpass}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:-supersecretuserpass}
    networks:
      - wordpress_net
    deploy:
      replicas: 1 # Databases typically don't scale horizontally in Swarm without complex setups
      restart_policy:
        condition: on-failure

volumes:
  wordpress_data:
  db_data: # Persistent volume for database
# ... rest of the docker-compose.yml

Note the use of environment variables for sensitive information like passwords. These should ideally be managed using Docker Secrets or AWS Secrets Manager in a production environment.

Deploying to Docker Swarm

Once your docker-compose.yml file and Nginx configuration are in place, you can deploy your WordPress stack to your Docker Swarm cluster. Ensure you have a Swarm initialized and your nodes are ready.

Initialization and Deployment Commands

First, initialize your Docker Swarm if you haven’t already:

# On your manager node
docker swarm init --advertise-addr 

Then, deploy your stack from the directory containing your docker-compose.yml file:

# Ensure you have .env file with MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD if not hardcoded
docker stack deploy -c docker-compose.yml wordpress_stack

You can check the status of your services:

docker stack services wordpress_stack
docker stack ps wordpress_stack

Integrating with AWS Load Balancing

Docker Swarm’s built-in ingress routing mesh is useful for internal load balancing, but for external access and integration with AWS services, an AWS Elastic Load Balancer (ELB) is necessary. We’ll use an Application Load Balancer (ALB) for its advanced routing capabilities and SSL termination.

ALB Target Group Configuration

You’ll need to create an ALB and configure its target groups. The target groups should point to the Docker Swarm nodes on the port exposed by the Swarm ingress. By default, Swarm exposes published ports on all nodes. For a service with ports: - "80:80", Swarm makes port 80 available on all nodes.

Target Group Setup:

  • Protocol: HTTP
  • Port: 80 (or the port your Swarm ingress is listening on for published ports)
  • Target Type: Instance
  • VPC: Your AWS VPC
  • Health Checks: Configure health checks to point to a specific URL on your WordPress site (e.g., /wp-cron.php or a custom health check endpoint) with an expected status code of 200. This ensures the ALB only routes traffic to healthy WordPress instances.

ALB Listener and Rules

Configure the ALB listener (typically on port 80 and 443 for HTTPS) to forward traffic to the target group you created. For HTTPS, you’ll need to attach an SSL certificate from AWS Certificate Manager (ACM).

Security Group Configuration

Ensure your EC2 instances running Docker Swarm have security groups that allow inbound traffic on the Swarm ingress port (typically 4789 for Swarm control plane, and the published port, e.g., 80/443, for application traffic) from the ALB’s security group. The ALB’s security group should allow inbound traffic on port 80/443 from your desired client IP ranges (e.g., 0.0.0.0/0).

Infrastructure as Code (IaC) with Terraform

To manage this infrastructure reliably and reproducibly, we’ll use Terraform. This allows us to define our AWS resources (VPC, EC2 instances, ALB, Security Groups, etc.) in code.

Terraform Configuration Snippet (AWS Provider and EC2)

Here’s a simplified example of how you might define your AWS provider and EC2 instances for your Docker Swarm nodes:

provider "aws" {
  region = "us-east-1"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "wordpress-swarm-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "us-east-1a"
  tags = {
    Name = "wordpress-swarm-public-subnet"
  }
}

resource "aws_security_group" "swarm_nodes" {
  name        = "swarm-nodes-sg"
  description = "Allow Swarm traffic and ALB access"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Restrict this in production
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    security_groups = [aws_security_group.alb.id] # Allow ALB
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    security_groups = [aws_security_group.alb.id] # Allow ALB
  }

  # Swarm management ports (adjust as needed)
  ingress {
    from_port   = 2377
    to_port     = 2377
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Restrict this
  }
  ingress {
    from_port   = 7946
    to_port     = 7946
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Restrict this
  }
  ingress {
    from_port   = 7946
    to_port     = 7946
    protocol    = "udp"
    cidr_blocks = ["0.0.0.0/0"] # Restrict this
  }
  ingress {
    from_port   = 4789
    to_port     = 4789
    protocol    = "udp"
    cidr_blocks = ["0.0.0.0/0"] # Restrict this
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "swarm-nodes-sg"
  }
}

resource "aws_instance" "swarm_manager" {
  ami           = "ami-0abcdef1234567890" # Replace with a current AMI ID
  instance_type = "t3.medium"
  subnet_id     = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.swarm_nodes.id]
  key_name      = "your-ssh-key" # Replace with your key pair name

  user_data = <<-EOF
              #!/bin/bash
              # Install Docker and Docker Swarm
              apt-get update -y
              apt-get install -y apt-transport-https ca-certificates curl software-properties-common
              curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
              add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
              apt-get update -y
              apt-get install -y docker-ce docker-ce-cli containerd.io
              usermod -aG docker ubuntu
              # Initialize Swarm (adjust IP)
              docker swarm init --advertise-addr ${self.private_ip}
              EOF

  tags = {
    Name = "swarm-manager-01"
    Role = "manager"
  }
}

# Add similar resources for worker nodes, joining the swarm using the token from the manager

Terraform Configuration Snippet (AWS ALB)

And here's how you might define the ALB, target group, and listener:

resource "aws_security_group" "alb" {
  name        = "alb-sg"
  description = "Allow HTTP/HTTPS from anywhere"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "wordpress-alb-sg"
  }
}

resource "aws_lb" "wordpress_alb" {
  name               = "wordpress-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = aws_subnet.public.ids # Use multiple subnets for HA

  tags = {
    Name = "wordpress-alb"
  }
}

resource "aws_lb_target_group" "wordpress_tg" {
  name     = "wordpress-tg"
  port     = 80
  protocol = "HTTP"
  vpc_id   = aws_vpc.main.id

  health_check {
    path                = "/wp-cron.php" # Or a custom health check endpoint
    protocol            = "HTTP"
    matcher             = "200"
    interval            = 30
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }

  tags = {
    Name = "wordpress-tg"
  }
}

resource "aws_lb_listener" "wordpress_http_listener" {
  load_balancer_arn = aws_lb.wordpress_alb.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.wordpress_tg.arn
  }
}

# Add HTTPS listener with ACM certificate for production
# resource "aws_lb_listener" "wordpress_https_listener" { ... }

Orchestration and Management

With Docker Swarm managing the application containers and AWS ALB handling external traffic, you have a robust, highly available WordPress setup. Key management aspects include:

  • Scaling: Adjust the replicas count in your docker-compose.yml for WordPress and PHP-FPM services. Swarm will automatically provision new containers.
  • Updates: Use docker stack deploy with rolling updates. The update_config in the compose file controls the rollout strategy.
  • Monitoring: Implement monitoring for your Swarm nodes (CPU, memory, disk) and application health (via ALB health checks and application-level metrics). Consider tools like Prometheus and Grafana.
  • Logging: Centralize logs from your Docker containers using a logging driver (e.g., `awslogs` to CloudWatch Logs) or a dedicated logging solution like ELK stack.
  • Database Backups: Regularly back up your MariaDB data volume. For production, AWS RDS with automated backups is highly recommended.

Considerations for Production

While this setup provides high availability, several points are critical for a production environment:

  • Managed Database: Replace the self-hosted MariaDB with AWS RDS for managed backups, replication, and failover.
  • Persistent Storage: For database data, use AWS EBS volumes managed by Terraform for better performance and reliability than Docker volumes on EC2.
  • Secrets Management: Use AWS Secrets Manager or HashiCorp Vault for managing database credentials and other sensitive information, rather than environment variables or Docker Secrets directly.
  • CI/CD Pipeline: Automate the build, test, and deployment process using a CI/CD tool (e.g., Jenkins, GitLab CI, AWS CodePipeline).
  • CDN: Integrate with a Content Delivery Network (CDN) like AWS CloudFront for caching static assets closer to users, reducing load on your Swarm nodes.
  • WAF: Deploy AWS WAF with your ALB to protect against common web exploits.

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

  • Orchestrating High-Availability WordPress with Docker Swarm and AWS Load Balancing: A Deep Dive into Infrastructure as Code
  • Leveraging PHP 8.3’s JIT and Vector API for High-Performance WordPress Headless Backends on AWS Fargate
  • Leveraging PHP 8.3 JIT and Laravel Octane for Sub-Millisecond API Responses: A Performance Deep Dive
  • Orchestrating Microservices with Docker Swarm: A Scalable and Resilient WordPress Headless Architecture
  • Beyond `php-fpm`: Orchestrating High-Concurrency PHP with Custom Event Loops and WebSockets on Kubernetes

Categories

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

Recent Posts

  • Orchestrating High-Availability WordPress with Docker Swarm and AWS Load Balancing: A Deep Dive into Infrastructure as Code
  • Leveraging PHP 8.3's JIT and Vector API for High-Performance WordPress Headless Backends on AWS Fargate
  • Leveraging PHP 8.3 JIT and Laravel Octane for Sub-Millisecond API Responses: A Performance Deep Dive

Top Categories

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

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