Skip to content

Latest commit

 

History

History
342 lines (247 loc) · 11.3 KB

File metadata and controls

342 lines (247 loc) · 11.3 KB

WordPress Docker Stack

CI Version Status License

Table of Contents

Overview

This repository provides a Docker Compose-based WordPress stack for both local development and production deployments, with a shared base, clear separation of concerns, and explicit operational workflows.

The project supports both development and production profiles, with script-driven automation for initialization, URL synchronization, and database backups.

Reading Guide

Typical Use Cases

  1. Fresh WordPress setup: Start a new instance with make up (development) or make up-prod (production).
  2. Import an existing WordPress project: Place a SQL dump in db/init/, copy your wp-content assets into src/, and use make db-restore SQL_FILE=<file.sql> when you need a manual restore.
  3. Environment migration and URL synchronization: wp-init reads the current site URL and runs a controlled wp search-replace toward SITE_URL.
  4. Continuous database safety: db-backup creates periodic SQL backups and applies FIFO retention.

Development Quick Start

Prerequisites

  • Docker
  • Docker Compose
  • GNU Make

Commands in this README assume a POSIX-like shell. On Windows, use Git Bash, WSL, or an equivalent environment that provides make and cp.

Setup

git clone https://github.com/taygumus/wp-docker-stack.git
cd wp-docker-stack
cp .env.example .env

The default values in .env.example are suitable for a first local run.

Start development stack

make up

Access

  • WordPress: http://<SERVER_NAME>:<HTTP_PORT> (default: http://localhost:8000)
  • phpMyAdmin (optional): http://localhost:<PHPMYADMIN_PORT> (default: 8001)

Stop development stack

make down

Production Quick Start

The production profile is designed to run behind an external reverse proxy.

Prepare environment variables

  • Copy .env.example to .env (if not already done).
  • Replace the example database credentials before any non-local deployment. Do not use the default .env.example secrets in production.
  • Set SERVER_NAME to your public hostname.
  • Set SITE_URL to https://<SERVER_NAME>.

Prepare networking

Create the external proxy network (one-time operation):

docker network create proxy

If the network already exists, Docker reports it and you can continue.

Start production stack

make up-prod

View production logs

make logs-prod

Route traffic

In your reverse proxy vhost for SERVER_NAME, forward traffic to the upstream alias wp-docker-stack-nginx on port 80 over Docker network proxy.

Example:

location / {
    proxy_pass http://wp-docker-stack-nginx:80;
}

For a ready-to-use Nginx + Certbot edge setup, see Nginx Docker Reverse Proxy.

Stop production stack

make down-prod

Capacity planning (production)

Baseline sizing for typical small deployments:

Scenario vCPU RAM Notes
Minimum 1 1 GB Suitable for low traffic and small datasets.
Recommended 2 2 GB Better headroom for MySQL activity and plugin/theme load.
Growth-ready 2-4 4 GB+ Better resilience for spikes and heavier workloads.

Typical idle/light-load footprint:

  • MySQL: around 350-600 MB (can increase with data size and query complexity)
  • WordPress PHP-FPM: around 80-200 MB
  • Nginx + sidecars: around 40-120 MB
  • Safety headroom: keep at least 20-30% free RAM

Runtime note: production resource values are declared in deploy.resources. Effective enforcement depends on your container runtime/orchestrator. Validate real usage on your host with docker stats --no-stream.

Configuration

All behavior is configured through .env values.

Shared settings (all profiles)

Variable Description
SERVER_NAME Public hostname/domain used by Nginx and URL generation.
DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD MySQL app credentials used by WordPress and sidecars.
DATABASE_ROOT_PASSWORD MySQL root password for administrative actions.
SKIP_WP_INIT Skip wp-init tasks when set to true.
SITE_URL Target WordPress URL used by synchronization.
SKIP_COLUMNS Comma-separated columns excluded from wp search-replace (default: guid).
SKIP_DB_BACKUP Disable periodic backup sidecar when set to true.
DATABASE_BACKUP_INITIAL_DELAY Delay before first backup (s/m/h/d).
DATABASE_BACKUP_INTERVAL Backup interval (s/m/h/d).
DATABASE_BACKUP_MAX_FILES Maximum retained .sql files (FIFO).

Development settings (docker-compose.dev.yml)

Variable Description
HTTP_PORT Host port mapped to Nginx.
PHPMYADMIN_PORT Host port for phpMyAdmin.

Development profile also mounts:

  • ./src into wp-content
  • ./db/init into MySQL init directory (processed automatically only when the database volume is initialized for the first time)
  • ./db/backups for host-visible backup files

Production settings (docker-compose.prod.yml)

Variable Description
LOG_SIZE, LOG_FILES Container log rotation settings.
DB_CPUS, DB_MEM_LIMIT Declared resource settings for MySQL.
WP_CPUS, WP_MEM_LIMIT Declared resource settings for WordPress.
NGINX_CPUS, NGINX_MEM_LIMIT Declared resource settings for Nginx.
WP_INIT_CPUS, WP_INIT_MEM_LIMIT Declared resource settings for wp-init.
DB_BACKUP_CPUS, DB_BACKUP_MEM_LIMIT Declared resource settings for db-backup.

Production profile uses named volume db_backups and external network proxy.

Operational Commands

Makefile is the main interface for day-to-day operations.

Development lifecycle

Command Description
make up Build and start development services (docker-compose.yml + docker-compose.dev.yml).
make down Stop development services.
make clean Stop development services and remove volumes (destructive: deletes database and WordPress data).
make reset Full reset (clean + up; destructive for persistent data).
make logs Stream development logs.

Production lifecycle

Command Description
make up-prod Start production services (docker-compose.yml + docker-compose.prod.yml).
make down-prod Stop production services.
make logs-prod Stream production logs.

Maintenance commands (development profile)

Command Description
make sync-site-url Trigger manual site URL synchronization.
make db-backup Run one-off database backup.
make db-restore SQL_FILE=<file.sql> Restore a dump from db/init/ (basename only).

Architecture & Workflow

The stack is organized into presentation, application, data, and operations services.

Compose layering

flowchart LR
    Base["docker-compose.yml (base)"] --> Dev["docker-compose.dev.yml (dev)"]
    Base --> Prod["docker-compose.prod.yml (prod)"]
Loading

System diagram

Solid arrows show runtime traffic and data dependencies. Dashed arrows show optional or operator-driven interactions.

flowchart LR
    Visitor((Visitor))
    Operator((Operator))
    Proxy["External reverse proxy"]
    ProxyNet["Network: proxy"]

    subgraph Edge["Presentation layer"]
        direction TB
        Nginx[Nginx]
        PMA["phpMyAdmin (dev only)"]
    end

    subgraph App["Application layer"]
        direction TB
        WP[WordPress]
    end

    subgraph Data["Data layer"]
        direction TB
        DB[(MySQL)]
        V_DB[(db_data volume)]
        V_WP[(wordpress volume)]
        V_BKP["Backups (dev bind / prod volume)"]
    end

    subgraph Ops["Operations plane"]
        direction TB
        WP_INIT[wp-init]
        DB_BACKUP[db-backup]
        WP_CLI["wp-cli (dev only)"]
        DB_CLI["db-cli (dev only)"]
    end

    Visitor -. dev .-> Nginx
    Visitor -->|production| Proxy --> Nginx
    Proxy -. attached .-> ProxyNet
    Nginx -. attached in prod .-> ProxyNet

    Nginx --> WP --> DB

    DB --- V_DB
    WP --- V_WP
    WP_INIT --- V_WP
    DB_BACKUP --- V_BKP

    PMA -.-> DB
    WP_CLI -.-> WP
    DB_CLI -.-> DB
    WP_INIT --> DB
    DB_BACKUP --> DB

    Operator -.-> PMA
    Operator -.-> WP_CLI
    Operator -.-> DB_CLI
    Operator -.-> WP_INIT
    Operator -.-> DB_BACKUP
Loading

Service responsibilities

Service Role Profile
Nginx Reverse proxy and static entrypoint to PHP-FPM. Development + Production
WordPress Application runtime (PHP-FPM). Development + Production
Database Persistent MySQL storage (db_data). Development + Production
wp-init One-shot URL detection and synchronization. Development + Production
db-backup Periodic backup and FIFO rotation. Development + Production
wp-cli Stateless WordPress maintenance shell. Development only
db-cli Stateless MySQL maintenance shell. Development only
phpMyAdmin Optional DB web UI. Development only

Design Decisions

  • Explicit automation: initialization, migration, and backup behavior is script-driven and auditable.
  • Layered composition: a shared base runtime is extended through development and production profiles.
  • Operational sidecars: lifecycle tasks stay isolated from request-serving services.
  • Production hardening: production profile adds logging policy, security options, and proxy-network integration.

Quality Gates and CI

The GitHub Actions workflow (.github/workflows/ci-lint.yml) validates:

  • Shell scripts with shellcheck
  • Compose files with yamllint
  • Compose resolution for base + development profile via docker compose config
  • Makefiles with checkmake
  • Markdown files with markdownlint

Extensibility

This structure supports incremental growth without rewriting the core stack:

  • add new Compose overlays (for example, staging)
  • add new operational sidecars under scripts/
  • integrate different reverse proxy frontends on network proxy
  • extend backup retention and external backup destinations

Contributions

Contributions are welcome. Please keep changes aligned with the layered architecture and ensure CI checks pass.