Leveraging Laravel Octane and Docker Swarm for Scalable, High-Performance WordPress Headless Applications
Architectural Overview: Headless WordPress with Laravel Octane on Docker Swarm
This document outlines a robust, scalable, and high-performance architecture for headless WordPress applications. We leverage Laravel Octane for accelerated PHP execution and Docker Swarm for container orchestration, providing a resilient and easily manageable deployment environment. This approach is particularly suited for applications demanding low latency, high throughput, and seamless scalability.
Core Components and Their Roles
- WordPress (Headless): The content management system, exposed via REST API or GraphQL.
- Laravel Octane: A high-performance application server for Laravel, significantly boosting response times by keeping the application’s bootstrap process in memory.
- Docker Swarm: A native clustering and orchestration solution for Docker containers, simplifying deployment, scaling, and management of distributed applications.
- Nginx: Acts as a reverse proxy, load balancer, and static file server, directing traffic to Octane workers and serving assets efficiently.
- Database (e.g., MySQL/MariaDB): Stores WordPress content and configuration.
- Redis/Memcached: Used for caching Octane’s application state and WordPress object caching.
Setting Up the WordPress Environment
For a headless setup, we’ll focus on the WordPress core and its API capabilities. The frontend will be a separate application (e.g., React, Vue, Next.js) consuming the WordPress API. We’ll containerize WordPress itself, ensuring it runs in a stable environment.
WordPress Dockerfile
A minimal Dockerfile for WordPress, focusing on serving the REST API. We’ll use an official WordPress image and add necessary configurations.
# Use an official WordPress image as a parent image FROM wordpress:latest # Set environment variables for database connection ENV WORDPRESS_DB_HOST=db:3306 ENV WORDPRESS_DB_USER=wordpress ENV WORDPRESS_DB_PASSWORD=password ENV WORDPRESS_DB_NAME=wordpress # Copy custom configurations if needed (e.g., wp-config.php) # COPY wp-config.php /var/www/html/wp-config.php # Expose the port WordPress runs on EXPOSE 80
Integrating Laravel Octane
Laravel Octane will serve as the application server for our Laravel application that interacts with WordPress. This could be a custom Laravel application acting as an API gateway or a direct Laravel-based CMS. For simplicity, we assume a standard Laravel project where Octane is enabled.
Enabling Octane in Laravel
First, install Octane:
composer require laravel/octane php artisan octane:install
Then, configure Octane. The key is to select a suitable application server. For production, Swoole or RoadRunner are recommended. Here, we’ll use Swoole.
// config/octane.php
return [
/*
|--------------------------------------------------------------------------
| Application Server
|--------------------------------------------------------------------------
|
| This option specifies the application server that will be used to serve
| your Octane application. Supported options are "swoole", "roadrunner",
| "frankenphp", and "octane".
|
*/
'server' => env('OCTANE_SERVER', 'swoole'),
/*
|--------------------------------------------------------------------------
| Swoole Configuration
|--------------------------------------------------------------------------
|
| These options configure the Swoole HTTP server.
|
*/
'swoole' => [
'listen' => env('OCTANE_SWOOLE_LISTEN', '0.0.0.0'),
'port' => env('OCTANE_SWOOLE_PORT', 8000),
'mode' => env('OCTANE_SWOOLE_MODE', SWOOLE_PROCESS), // SWOOLE_THREAD or SWOOLE_SERIAL
'options' => [
'worker_num' => env('OCTANE_SWOOLE_WORKERS', 4), // Adjust based on CPU cores
'max_request' => env('OCTANE_SWOOLE_MAX_REQUEST', 10000),
'enable_coroutine' => true,
'log_level' => SWOOLE_LOG_INFO,
'pid_file' => storage_path('swoole.pid'),
],
],
// ... other configurations
];
Octane Dockerfile
This Dockerfile builds a PHP-FPM image with Swoole extension, suitable for running Laravel Octane.
FROM php:8.2-fpm
# Install Swoole extension
RUN pecl install swoole \
&& docker-php-ext-enable swoole
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Set working directory
WORKDIR /var/www/html
# Copy application code
COPY . /var/www/html
# Install dependencies
RUN composer install --no-dev --optimize-autoloader
# Expose the port Octane will listen on
EXPOSE 8000
Docker Swarm Orchestration
Docker Swarm allows us to define our application’s services, their configurations, and how they scale. We’ll use a docker-compose.yml file to define the services.
Docker Compose File for Swarm
This docker-compose.yml defines the WordPress, Octane application, Nginx, and database services. We’ll use Docker Swarm’s overlay network for inter-container communication.
version: '3.8'
services:
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: password
networks:
- app-network
deploy:
replicas: 1
restart_policy:
condition: on-failure
wordpress:
build:
context: ./wordpress # Directory containing your WordPress Dockerfile
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: wordpress
networks:
- app-network
depends_on:
- db
deploy:
replicas: 2 # Scale WordPress instances if needed for API load
restart_policy:
condition: on-failure
octane_app:
build:
context: . # Assuming your Laravel Octane app is in the root
environment:
APP_ENV: production
APP_KEY: base64:YOUR_APP_KEY_HERE # Generate with php artisan key:generate
DB_HOST: db
DB_DATABASE: wordpress
DB_USERNAME: wordpress
DB_PASSWORD: password
REDIS_HOST: redis
OCTANE_SWOOLE_PORT: 8000
OCTANE_SWOOLE_WORKERS: 2 # Adjust based on server resources
networks:
- app-network
depends_on:
- db
- redis
deploy:
replicas: 4 # Scale Octane workers based on expected traffic
restart_policy:
condition: on-failure
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro # For SSL certificates
networks:
- app-network
depends_on:
- octane_app
deploy:
replicas: 2 # High availability for Nginx
restart_policy:
condition: on-failure
redis:
image: redis:latest
networks:
- app-network
deploy:
replicas: 1
restart_policy:
condition: on-failure
networks:
app-network:
driver: overlay
attachable: true
volumes:
db_data:
Nginx Configuration
The Nginx configuration is crucial for routing traffic. It will proxy requests to the Octane application workers and serve static assets directly.
# nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream octane_workers {
# Use Docker Swarm's DNS round-robin for octane_app service
# The number of servers here should ideally match the replica count in docker-compose.yml
server octane_app:8000;
# If you have multiple octane_app replicas, Swarm handles load balancing
}
server {
listen 80;
server_name your-domain.com; # Replace with your domain
# Serve static assets directly from the Laravel public directory
location / {
proxy_pass http://octane_workers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off; # Important for Octane/Swoole
}
# Optional: Serve WordPress REST API requests directly if Nginx is also serving WordPress
# This is less common in a pure headless setup where Octane handles API calls.
# If WordPress is served by its own container and Nginx is the entry point:
# location /wp-json/ {
# proxy_pass http://wordpress:80; # Assuming wordpress service is named 'wordpress'
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
# Serve static files from Laravel's public directory
location ~ ^/(index\.php|.*\.php)(/|$) {
# This block is typically for traditional PHP-FPM, not Octane.
# For Octane, all requests go to proxy_pass above.
# If you need to serve static files from Laravel's public dir:
# location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
# root /var/www/html/public;
# expires 30d;
# add_header Cache-Control "public";
# }
}
}
# Optional: SSL configuration
# server {
# listen 443 ssl;
# server_name your-domain.com;
#
# ssl_certificate /etc/nginx/ssl/your-domain.com.crt;
# ssl_certificate_key /etc/nginx/ssl/your-domain.com.key;
#
# # ... same proxy_pass directives as above
# }
}
Deployment and Management
Initializing Docker Swarm
On your manager node:
docker swarm init --advertise-addr
On your worker nodes, join the swarm:
docker swarm join --token:2377
Deploying the Stack
Navigate to the directory containing your docker-compose.yml and run:
docker stack deploy -c docker-compose.yml my_headless_app
Scaling Services
You can scale services independently using the docker service scale command or by updating the replicas count in your docker-compose.yml and redeploying.
# Scale Octane workers to 8 instances docker service scale my_headless_app_octane_app=8 # Scale Nginx to 3 instances for higher availability docker service scale my_headless_app_nginx=3
Performance Tuning and Monitoring
Octane Configuration Tuning
The config/octane.php file offers several tuning parameters:
server: Choose betweenswoole,roadrunner,frankenphp. Swoole is generally performant for I/O-bound tasks.swoole.options.worker_num: Set this to the number of CPU cores available to the container.swoole.options.max_request: Limits the number of requests a worker can handle before restarting, preventing memory leaks.swoole.mode:SWOOLE_PROCESSis recommended for most use cases.SWOOLE_THREADcan offer benefits but requires careful handling of shared state.
Database and Cache Optimization
Ensure your database (MySQL/MariaDB) is properly configured for performance. For caching, leverage Redis. Octane uses Redis for state management, and WordPress can be configured to use Redis for object caching via plugins like “Redis Object Cache”.
Nginx Optimization
Key Nginx directives for performance:
proxy_buffering off;: Crucial when proxying to Octane/Swoole to avoid buffering responses, leading to lower latency.keepalive_timeout: Adjust based on expected client connection patterns.sendfile on;: Efficiently transfers files from disk to the network.
Monitoring
Implement robust monitoring for your Docker Swarm services. Tools like Prometheus and Grafana can be deployed to track container resource usage (CPU, memory), network traffic, request latency, and error rates for each service (Nginx, Octane, WordPress, DB).
Security Considerations
When deploying in production:
- Secure Database Credentials: Use Docker secrets or environment variables managed securely.
- SSL/TLS Encryption: Configure Nginx to use HTTPS for all traffic.
- Firewall Rules: Restrict access to necessary ports only.
- WordPress Security: Keep WordPress core, themes, and plugins updated. Consider security plugins.
- Octane Security: Ensure your Laravel application is secure, especially if it exposes any endpoints.
Conclusion
This architecture provides a powerful foundation for building highly scalable and performant headless WordPress applications. By combining Laravel Octane’s speed with Docker Swarm’s orchestration capabilities, you can achieve low latency, high availability, and efficient resource utilization, making it ideal for demanding web applications and APIs.