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

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Dockerizing and Orchestrating Legacy WooCommerce Systems on Modern DigitalOcean Infrastructure

Dockerizing and Orchestrating Legacy WooCommerce Systems on Modern DigitalOcean Infrastructure

Assessing Legacy WooCommerce Dependencies

Before embarking on containerization, a thorough audit of the existing WooCommerce installation is paramount. Legacy systems often harbor implicit dependencies on specific PHP versions, extensions, and even operating system-level libraries that are not immediately obvious. A common pitfall is assuming a direct 1:1 mapping of the current environment to a container. We must identify:

  • PHP version and required extensions (e.g., mysqli, gd, imagick, zip, intl, mbstring).
  • Web server configuration (Apache or Nginx) and any custom rewrite rules or directives.
  • Database version and specific configurations (e.g., character set, collation, storage engine).
  • External service integrations (payment gateways, shipping APIs, CRM hooks) and their communication protocols.
  • File system permissions and ownership requirements for uploads, cache, and logs.

Tools like phpinfo(), coupled with manual inspection of wp-config.php, theme/plugin code, and server logs, are essential. For a more automated approach, consider a simple PHP script to list loaded extensions and their versions:

<?php
phpinfo();
?>

Additionally, a script to check for common WooCommerce-required extensions:

<?php
$required_extensions = [
    'mysqli', 'gd', 'imagick', 'zip', 'intl', 'mbstring', 'curl', 'openssl', 'dom', 'simplexml', 'xml', 'json', 'session', 'ctype', 'filter', 'hash', 'iconv', 'libxml', 'pcre', 'SPL', 'standard', 'tokenizer', 'zlib'
];

echo "<h2>PHP Extension Check</h2>";
echo "<ul>";

foreach ($required_extensions as $extension) {
    if (extension_loaded($extension)) {
        echo "<li style='color: green;'>" . htmlspecialchars($extension) . " (Loaded)</li>";
    } else {
        echo "<li style='color: red;'>" . htmlspecialchars($extension) . " (NOT LOADED)</li>";
    }
}
echo "</ul>";

echo "<h2>PHP Version</h2>";
echo phpversion();
?>

Crafting the Dockerfile for WooCommerce

The core of our containerization strategy lies in a robust Dockerfile. We’ll opt for an official PHP image as a base, layering on Nginx for serving static assets and PHP-FPM for processing dynamic requests. This separation is crucial for performance and scalability.

A typical Dockerfile might look like this:

# Use an official PHP image with Apache/Nginx and extensions
# Example: PHP 8.1 with FPM and common extensions
FROM php:8.1-fpm

# Set working directory
WORKDIR /var/www/html

# Install system dependencies
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libzip-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libwebp-dev \
    libicu-dev \
    libxslt1-dev \
    libonig-dev \
    libxml2-dev \
    libssl-dev \
    libcurl4-openssl-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
    libwebp-dev \
    libfreetype6-dev \
    libzip-dev \
    libxslt1-dev \
    libonig-dev \
    libxml2-dev \
    libssl-dev \
    libcurl4-openssl-dev \
    && rm -rf /var/lib/apt/lists/*

# Install PHP extensions
RUN docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp \
    && docker-php-ext-install -j$(nproc) gd \
    && docker-php-ext-install -j$(nproc) zip \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) opcache \
    && docker-php-ext-install -j$(nproc) pdo_mysql \
    && docker-php-ext-install -j$(nproc) sockets \
    && docker-php-ext-enable xdebug # Only for development

# Install Imagick (if needed and available)
RUN apt-get update && apt-get install -y libmagickwand-dev --no-install-recommends \
    && pecl install imagick \
    && docker-php-ext-enable imagick \
    && rm -rf /var/lib/apt/lists/*

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

# Copy WooCommerce and plugins (or manage via Composer)
# For simplicity, we'll copy them here. In production, consider Composer for dependencies.
COPY ./wordpress/ /var/www/html/
COPY ./wp-content/plugins/ /var/www/html/wp-content/plugins/
COPY ./wp-content/themes/ /var/www/html/wp-content/themes/

# Configure PHP-FPM
COPY docker/php-fpm/zz-docker.conf /usr/local/etc/php-fpm.d/zz-docker.conf

# Expose port 9000 for PHP-FPM
EXPOSE 9000

# Command to run PHP-FPM
CMD ["php-fpm"]

The zz-docker.conf file is crucial for tuning PHP-FPM for a containerized environment:

; /usr/local/etc/php-fpm.d/zz-docker.conf
; Adjust settings for Docker environment

[global]
; Use 'ondemand' or 'dynamic' for better resource utilization in containers
; 'static' can be useful for predictable load but might waste resources.
; For WooCommerce, 'dynamic' is often a good balance.
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 5
pm.max_requests = 500 ; Restart workers to clear memory leaks

; Increase memory limit for WooCommerce operations
memory_limit = 512M

; Increase post_max_size and upload_max_filesize for media uploads
post_max_size = 64M
upload_max_filesize = 64M

; Set appropriate user/group for file permissions
user = www-data
group = www-data

; Set error reporting for debugging (adjust for production)
error_reporting = E_ALL
display_errors = Off
log_level = notice
; log_errors = On
; error_log = /var/log/php-fpm/error.log

; Set timezone
date.timezone = UTC

Nginx Configuration for Serving WooCommerce

A separate Nginx container will handle incoming HTTP requests, serve static assets, and proxy dynamic requests to the PHP-FPM container. This decouples web serving from PHP processing.

Here’s a sample Nginx configuration for a WooCommerce site:

# /etc/nginx/conf.d/default.conf

# Serve static files directly
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
    expires 30d;
    add_header Cache-Control "public";
    access_log off;
    try_files $uri $uri/ =404;
}

# PHP-FPM configuration
location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php-fpm:9000; # 'php-fpm' is the service name in docker-compose
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;

    # WooCommerce specific optimizations
    fastcgi_read_timeout 300; # Increase timeout for long operations
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
}

# Deny access to sensitive files
location ~ /\.ht {
    deny all;
}

# WordPress permalinks
location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}

# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"; # CSP can be complex, tune carefully

# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

# Disable access to wp-config.php
location ~* wp-config\.php {
    deny 127.0.0.1;
    deny ::1;
    deny all;
}

Database Containerization (MySQL/MariaDB)

A dedicated database container is essential. We’ll use an official MySQL or MariaDB image. Persistent storage for the database is critical, achieved through Docker volumes.

# docker-compose.yml snippet for database
services:
  db:
    image: mariadb:10.6 # Or mysql:8.0
    container_name: woocommerce_db
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} # Use .env file for secrets
      MYSQL_DATABASE: woocommerce_db
      MYSQL_USER: woocommerce_user
      MYSQL_PASSWORD: ${MYSQL_PASSWORD} # Use .env file for secrets
    ports:
      - "3306:3306" # Expose only if direct access is needed, otherwise omit for security
    networks:
      - woocommerce_network

volumes:
  db_data:

Ensure your .env file contains the necessary credentials:

# .env file
MYSQL_ROOT_PASSWORD=your_super_secret_root_password
MYSQL_PASSWORD=your_woocommerce_db_password

Orchestration with Docker Compose

docker-compose.yml is the orchestrator, defining the services, networks, and volumes for our WooCommerce stack. We’ll define at least three services: Nginx, PHP-FPM, and the database.

# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:stable-alpine
    container_name: woocommerce_nginx
    ports:
      - "80:80"
      - "443:443" # If using SSL
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d # Mount custom Nginx config
      - ./certs:/etc/nginx/certs # Mount SSL certificates if used
      - ./wordpress:/var/www/html # Mount WordPress files (or use a named volume)
      - ./logs/nginx:/var/log/nginx # Mount Nginx logs
    depends_on:
      - php-fpm
    restart: always
    networks:
      - woocommerce_network

  php-fpm:
    build:
      context: . # Path to your Dockerfile
      dockerfile: Dockerfile
    container_name: woocommerce_php_fpm
    volumes:
      - ./wordpress:/var/www/html # Mount WordPress files (or use a named volume)
      - ./logs/php-fpm:/var/log/php-fpm # Mount PHP-FPM logs
    expose:
      - "9000" # Expose PHP-FPM port internally
    depends_on:
      - db
    restart: always
    networks:
      - woocommerce_network

  db:
    image: mariadb:10.6
    container_name: woocommerce_db
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: woocommerce_db
      MYSQL_USER: woocommerce_user
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - woocommerce_network

networks:
  woocommerce_network:
    driver: bridge

volumes:
  db_data:

To build and run the containers:

# Create .env file with your database credentials
cp .env.example .env # If you have a template

# Build and start services
docker-compose up -d --build

# View logs
docker-compose logs -f

# Stop services
docker-compose down

DigitalOcean Infrastructure Setup

On DigitalOcean, we can leverage Droplets to host our Docker environment. For production, consider a managed Kubernetes service (DOKS) for enhanced scalability and resilience, but for a direct Docker Compose deployment, a robust Droplet is sufficient.

  • Droplet Configuration: Choose a Droplet size with adequate CPU and RAM. For a moderately trafficked WooCommerce site, a 4GB RAM / 2 vCPU Droplet is a good starting point. Ensure you select a recent Ubuntu LTS version (e.g., 22.04).
  • Docker Installation: SSH into your Droplet and install Docker and Docker Compose.
# Update package list
sudo apt-get update

# Install Docker CE
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

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-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

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

# 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 installation
docker --version
docker-compose --version

Deployment Workflow:

  • Clone your application code (including Dockerfiles and docker-compose.yml) to the Droplet.
  • Ensure your .env file is correctly configured on the server.
  • Run docker-compose up -d --build to deploy.
  • Configure DNS to point your domain to the Droplet’s IP address.
  • Set up a firewall (e.g., UFW) to allow HTTP/HTTPS traffic.
# Example UFW configuration
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

Scaling and High Availability Considerations

For true scalability and high availability, Docker Compose on a single Droplet is insufficient. The next steps involve moving to a container orchestration platform like Kubernetes (DigitalOcean Kubernetes Service – DOKS).

  • Horizontal Scaling: DOKS allows you to scale your Nginx and PHP-FPM deployments independently by increasing the number of pods.
  • Load Balancing: DOKS integrates with DigitalOcean’s Load Balancers to distribute traffic across your Nginx pods.
  • Persistent Storage: Utilize DigitalOcean Block Storage or Spaces for persistent volumes for your database and potentially WordPress uploads.
  • Database HA: For critical applications, consider managed database services (like DigitalOcean Managed Databases) or advanced Kubernetes database operators for replication and failover.
  • CI/CD Integration: Automate your build, test, and deployment pipeline using tools like GitLab CI, GitHub Actions, or Jenkins, pushing container images to a registry (e.g., Docker Hub, DigitalOcean Container Registry).

Transitioning from Docker Compose to Kubernetes involves rewriting your docker-compose.yml into Kubernetes manifests (Deployments, Services, Ingress, PersistentVolumeClaims). This is a significant architectural shift but necessary for robust, scalable cloud-native applications.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing indexing lock conflicts and high CPU during bulk stock updates on DigitalOcean Servers
  • How to Debug and Fix memory leaks and socket exhaustion in daemon processes in Modern C++ Applications
  • Infrastructure as Code: Provisioning Secure PHP Clusters on DigitalOcean Using Terraform
  • Fixing Slow Largest Contentful Paint (LCP) caused by unoptimized database queries in Legacy Laravel Codebases Without Breaking API Contracts
  • An Auditor’s Checklist for Securing Laravel Backends on Google Cloud

Copyright © 2026 · Vinay Vengala