Skip to content

Repository files navigation

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))
    Proxy["External reverse proxy"]
    Nginx["Nginx"]
    WP["WordPress"]
    DB[("MySQL")]

    DevTools["`Development tools
wp-cli · db-cli · pma`"]
    OpsTools["`Operations services
wp-init · db-backup`"]
    Operator((Operator))

    WPVolume[("WordPress volume")]
    DBVolume[("Database volume")]
    Backups["`Backups
(dev bind / prod volume)`"]

    Visitor -->|production| Proxy --> Nginx --> WP --> DB
    Visitor -.->|development| Nginx

    Operator -.-> DevTools
    Operator -.-> OpsTools

    DevTools -.-> WP
    DevTools -.-> DB

    OpsTools -.-> WP
    OpsTools -.-> DB
    OpsTools -.-> Backups

    WP --- WPVolume
    DB --- DBVolume
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.

About

Docker Compose WordPress stack with automated initialization, backups, and utilities

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages