• 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 » Dockerizing and Orchestrating Legacy WordPress Systems on Modern DigitalOcean Infrastructure

Dockerizing and Orchestrating Legacy WordPress Systems on Modern DigitalOcean Infrastructure

Containerizing WordPress: The Foundation

Migrating legacy WordPress installations to a containerized environment offers significant advantages in terms of consistency, portability, and scalability. This section details the process of creating Docker images for WordPress and its dependencies, focusing on a production-ready setup.

Dockerfile for WordPress Core and PHP-FPM

We’ll start by crafting a Dockerfile that bundles WordPress core with PHP-FPM. This approach decouples the web server from the PHP execution, a common and robust pattern.

Consider a scenario where you need to manage custom plugins and themes. We’ll incorporate these directly into the image for simplicity, though for more dynamic deployments, volume mounts or separate image layers are preferable.

# Use an official PHP image with FPM and Apache (for serving static assets)
FROM php:8.1-fpm-apache

# Set working directory
WORKDIR /var/www/html

# Install necessary PHP extensions
RUN docker-php-ext-install pdo pdo_mysql zip exif gd && docker-php-ext-enable gd

# Install WordPress
RUN curl -o wordpress.tar.gz -SL https://wordpress.org/latest.tar.gz \
    && tar -xzf wordpress.tar.gz --strip-components=1 \
    && rm wordpress.tar.gz

# Copy custom plugins and themes (adjust paths as needed)
COPY ./wp-content/plugins/ /var/www/html/wp-content/plugins/
COPY ./wp-content/themes/ /var/www/html/wp-content/themes/

# Configure Apache to serve WordPress correctly
# Remove default Apache index.html
RUN rm -rf /var/www/html/index.html

# Enable Apache rewrite module for permalinks
RUN a2enmod rewrite

# Set correct permissions for WordPress files
RUN chown -R www-data:www-data /var/www/html

# Expose port 80 for Apache
EXPOSE 80

# Start Apache in foreground
CMD ["apache2-foreground"]

Dockerfile for MySQL Database

A separate container for the MySQL database is essential for maintainability and data management. We’ll use the official MySQL image and configure it for WordPress.

# Use an official MySQL image
FROM mysql:8.0

# Set environment variables for database initialization
ENV MYSQL_ROOT_PASSWORD=your_root_password
ENV MYSQL_DATABASE=wordpress_db
ENV MYSQL_USER=wordpress_user
ENV MYSQL_PASSWORD=your_wordpress_password

# Copy custom MySQL configuration if needed
# COPY ./my.cnf /etc/mysql/conf.d/my.cnf

# Expose MySQL port
EXPOSE 3306

Docker Compose for Orchestration

Docker Compose simplifies the management of multi-container Docker applications. It allows us to define and run our WordPress and MySQL services in a single command.

version: '3.8'

services:
  wordpress:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      - db
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress_db
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: your_wordpress_password
    networks:
      - wordpress_network

  db:
    build:
      context: .
      dockerfile: Dockerfile.db # Assuming Dockerfile.db for MySQL
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: wordpress_db
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: your_wordpress_password
    networks:
      - wordpress_network

volumes:
  wordpress_data:
  db_data:

networks:
  wordpress_network:

Note: In the docker-compose.yml, I’ve assumed a separate Dockerfile.db for the MySQL service. You would adapt the MySQL Dockerfile above to be named Dockerfile.db and place it in the same directory as your docker-compose.yml. Also, ensure the environment variables in docker-compose.yml match those in your MySQL Dockerfile.

DigitalOcean Droplet Setup and Configuration

For deploying this containerized WordPress on DigitalOcean, we’ll use a standard Droplet. The key is to install Docker and Docker Compose on the Droplet and then deploy our application.

Provisioning a DigitalOcean Droplet

Create a new Droplet on DigitalOcean. A general-purpose Droplet (e.g., 2 vCPU, 4GB RAM) should suffice for a moderately trafficked WordPress site. Choose an Ubuntu 22.04 LTS image for a stable environment.

Installing Docker and Docker Compose

Connect to your Droplet via SSH and execute the following commands to install Docker and Docker Compose:

# Update package list
sudo apt update
sudo apt upgrade -y

# Install Docker
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io

# Add current user to the docker group to run docker commands without sudo
sudo usermod -aG docker $USER
newgrp docker # Apply group changes to the current session

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Verify installations
docker --version
docker-compose --version

Deploying the WordPress Application

Transfer your Dockerfiles and docker-compose.yml to the Droplet. A common practice is to create a dedicated directory for your application, e.g., ~/wordpress-docker.

# Create application directory
mkdir ~/wordpress-docker
cd ~/wordpress-docker

# Upload your Dockerfiles and docker-compose.yml here using scp or other methods

# Build and start the containers
docker-compose up -d

This command will build the Docker images (if not already present) and start the WordPress and MySQL containers in detached mode. You can monitor the logs using docker-compose logs -f.

Production Considerations: Nginx as a Reverse Proxy

While the Apache server within the WordPress container can serve requests, for production environments, it’s highly recommended to use a dedicated reverse proxy like Nginx. This offers better performance, SSL termination, and load balancing capabilities.

Nginx Configuration for WordPress

We’ll run Nginx in its own container, forwarding requests to the WordPress container’s port 80.

# Dockerfile for Nginx Reverse Proxy
FROM nginx:alpine

# Remove default Nginx configuration
RUN rm /etc/nginx/conf.d/default.conf

# Copy custom Nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Expose port 80 and 443 (for SSL)
EXPOSE 80
EXPOSE 443
# nginx.conf
server {
    listen 80;
    server_name your_domain.com; # Replace with your domain

    # Redirect HTTP to HTTPS (if SSL is configured)
    # location / {
    #     return 301 https://$host$request_uri;
    # }

    location / {
        proxy_pass http://wordpress:80; # 'wordpress' is the service name in docker-compose.yml
        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_redirect off;
    }

    # Serve static assets directly from Nginx for performance
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
        root /var/www/html/wp-content; # Adjust path if your WP content is elsewhere
        expires 30d;
        access_log off;
    }
}

# Add SSL configuration here if needed
# server {
#     listen 443 ssl;
#     server_name your_domain.com;
#
#     ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
#     ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
#
#     # ... other SSL settings ...
#
#     location / {
#         proxy_pass http://wordpress:80;
#         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_redirect off;
#     }
# }

Update your docker-compose.yml to include the Nginx service:

version: '3.8'

services:
  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx # Assuming Dockerfile.nginx for Nginx
    ports:
      - "80:80"
      - "443:443" # If SSL is configured
    depends_on:
      - wordpress
    networks:
      - wordpress_network

  wordpress:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      - db
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress_db
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: your_wordpress_password
    networks:
      - wordpress_network

  db:
    build:
      context: .
      dockerfile: Dockerfile.db
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: your_root_password
      MYSQL_DATABASE: wordpress_db
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: your_wordpress_password
    networks:
      - wordpress_network

volumes:
  wordpress_data:
  db_data:

networks:
  wordpress_network:

Persistent Storage and Backups

The use of Docker volumes (wordpress_data and db_data) ensures that your WordPress files and MySQL data persist even if containers are recreated. For production, consider using DigitalOcean’s managed databases (like DigitalOcean Managed Databases for MySQL) or dedicated block storage for more robust data management and backup solutions.

Regular backups of both the WordPress files (from the wordpress_data volume) and the MySQL database are critical. You can automate this using cron jobs on the host Droplet that interact with the Docker volumes or by leveraging DigitalOcean’s snapshot features.

Scaling and High Availability

For higher traffic or improved availability, you can scale your WordPress deployment. This typically involves:

  • Multiple WordPress Instances: Run multiple instances of the WordPress container behind a load balancer (e.g., DigitalOcean Load Balancer or HAProxy).
  • Shared Storage: Use a shared network filesystem (like NFS) or object storage for WordPress uploads if multiple WordPress instances need to access them.
  • Database Replication: For read-heavy workloads, consider MySQL replication.
  • Container Orchestration: For more complex scaling and management, explore Kubernetes (e.g., DigitalOcean Kubernetes) or Docker Swarm.

When scaling WordPress instances, ensure that the WORDPRESS_DB_HOST environment variable in your docker-compose.yml points to the correct database service. If using a managed database, you’ll use its connection string instead of the Docker service name.

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

  • Step-by-Step Guide to building a custom custom charts dashboard block for Gutenberg using REST API custom routes
  • How to build custom Genesis child themes extensions utilizing modern Shortcode API schemas
  • How to securely integrate AWS S3 file uploads endpoints into WordPress custom plugins using Metadata API (add_post_meta)
  • Step-by-Step Guide to building a custom user session manager block for Gutenberg using Svelte standalone templates
  • Step-by-Step Guide to building a custom automated performance diagnostic log block for Gutenberg using REST API custom routes

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (586)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (810)
  • PHP (5)
  • PHP Development (23)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (546)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (20)
  • WordPress Theme Development (357)

Recent Posts

  • Step-by-Step Guide to building a custom custom charts dashboard block for Gutenberg using REST API custom routes
  • How to build custom Genesis child themes extensions utilizing modern Shortcode API schemas
  • How to securely integrate AWS S3 file uploads endpoints into WordPress custom plugins using Metadata API (add_post_meta)

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (810)
  • Debugging & Troubleshooting (586)
  • Security & Compliance (546)
  • SEO & Growth (492)
  • Business & Monetization (390)

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