- Overview
- Typical Use Cases
- Quick Start
- Configuration
- Operational Interface
- Architecture & Workflow
- Design Decisions
- Quality Gates and CI
- Extensibility
- Contributions
A Docker Compose–based WordPress environment focused on automation, reproducibility, and separation of concerns.
This repository provides a structured and repeatable way to run and operate WordPress using containers. All lifecycle tasks are handled through explicit configuration and script-driven automation, keeping application runtime and infrastructure responsibilities clearly separated.
The stack addresses common issues in containerized WordPress setups, such as implicit initialization logic, environment drift, and hard-to-audit automation, while remaining extensible for more advanced development and migration scenarios.
This project supports multiple workflows that commonly emerge when working with WordPress:
-
Fresh WordPress setup
Run a new WordPress instance with minimal configuration using Docker Compose and environment variables. -
Import an existing WordPress project
Reuse an existing WordPress installation by:- placing a database dump in
db/init/ - copying
wp-contentfiles intosrc/
The database is automatically initialized on first startup or restored manually when needed.
- placing a database dump in
-
Environment migration and site URL synchronization
When importing an existing database, the site URL stored in WordPress may not match the current environment (domain or port).
A dedicated initialization service detects the current site URL and synchronizes it with the configured environment to prevent redirect and startup issues. -
Continuous database safety
Database content is backed up automatically at configurable intervals using a FIFO rotation policy.
Backups and on-demand snapshots can also be triggered manually.
Once a relevant workflow is identified, the stack can be started and operated with a minimal setup.
This section provides the fastest path to a running environment using the default configuration.
- Docker
- Docker Compose
- GNU Make
Clone the repository and initialize the configuration:
git clone <repository-url>
cd wp-docker-stack
cp .env.example .env Orchestrate and launch all services:
make up- WordPress: Accessible at
http://<SERVER_NAME>:<HTTP_PORT>as configured in your.envfile. - Database Management: Available via the database CLI (
db-cli) or optional GUI tools such as phpMyAdmin.
Gracefully shut down all running services:
make downThe stack is driven by environment variables defined in the .env file. This approach keeps configuration explicit and avoids hardcoded values inside scripts or compose files.
| Variable | Description |
|---|---|
SERVER_NAME |
Domain or hostname for the application (e.g., localhost). |
HTTP_PORT |
Host port mapped to the Nginx entry point (e.g., 8000). |
Configures the MySQL instance used by both the DB engine and WordPress.
-
DATABASE_NAME,DATABASE_USER,DATABASE_PASSWORD -
DATABASE_ROOT_PASSWORD: Required for administrative tasks and CLI operations.
Handles the automated setup and URL synchronization to ensure the site is always reachable.
-
SKIP_WP_INIT: Set totrueto disable the initialization service duringmake up. -
SITE_URL: The target WordPress URL. Supports dynamic expansion (e.g.,http://${SERVER_NAME}:${HTTP_PORT}). -
SKIP_COLUMNS: Columns to exclude during the automatedsearch-replaceprocess (default:guid).
Manages automated snapshots and implements a data safety policy.
-
SKIP_DB_BACKUP: Set totrueto disable the automated backup service duringmake up. -
DATABASE_BACKUP_MAX_FILES: Number of historical snapshots to keep (FIFO rotation policy). -
DATABASE_BACKUP_INITIAL_DELAY: Wait time before the first backup (supportss/m/h/d, e.g.,60s). -
DATABASE_BACKUP_INTERVAL: Frequency of subsequent backups.
PHPMYADMIN_PORT: Host port for the optional phpMyAdmin web interface.
The Makefile provides a stable, minimal interface for common operations:
| Command | Description |
|---|---|
make up |
Build and start the environment. |
make down |
Stop all services. |
make clean |
Stop services and remove all volumes. |
make reset |
Full teardown (clean) and fresh restart (up). |
make logs |
Stream real-time logs from all containers. |
-
make sync-site-url: Manually trigger site URL synchronization. -
make db-backup: Execute a one-off database backup. -
make db-restore SQLFILE=x.sql: Restore a specific dump from thedb/directory.
This section describes the internal structure of the stack and is intended for users who want to understand, extend, or adapt the system beyond basic usage.
The design follows a Three-Tier Architecture for the application runtime, complemented by a dedicated Operations Plane for lifecycle management.
The diagram below illustrates the high-level relationships between runtime services, data persistence, and operational tooling. Solid arrows represent runtime dependencies, while dashed arrows indicate operational or administrative interactions.
flowchart TB
%% Actors
Visitor((Visitor))
Operator((Operator))
%% Presentation Layer
subgraph Edge [Presentation Layer]
direction TB
Nginx[Nginx]
PMA[phpMyAdmin]
end
%% Application Layer
subgraph App [Application Layer]
direction TB
WP[WordPress]
end
%% Data Layer
subgraph Data [Data Layer]
direction TB
DB[(Database)]
V_DB[(dbdata volume)]
V_WP[(wordpress volume)]
end
%% Operations Plane
subgraph Ops [Operations Plane]
direction TB
WP_INIT[wp-init]
DB_BACKUP[db-backup]
WP_CLI[wp-cli]
DB_CLI[db-cli]
end
%% Visitor flow (runtime)
Visitor --> Nginx
Nginx --> WP
WP --> DB
%% Persistence
DB --- V_DB
WP --- V_WP
%% Presentation dependencies
PMA -.-> DB
%% Operator interactions
Operator -.-> PMA
Operator -.-> WP_CLI
Operator -.-> DB_CLI
Operator -.-> WP_INIT
Operator -.-> DB_BACKUP
%% Operations interactions
WP_INIT --> WP
WP_INIT --> DB
WP_INIT --- V_WP
DB_BACKUP --> DB
WP_CLI -.-> WP
DB_CLI -.-> DB
-
Sidecar Pattern: Operations like initialization and backups run in dedicated, ephemeral containers. This ensures the application runtime remains immutable, secure, and focused solely on serving traffic.
-
Layered Composition: The environment is managed through a layered configuration to separate runtime concerns from development needs:
-
Base Stack (
docker-compose.yml): Orchestrates the essential services for a standalone, automated environment. -
Development Overrides (
docker-compose.dev.yml): Injects developer-centric features.
-
-
Script-Driven Automation: All logic resides in POSIX-compliant shell scripts under
scripts/. This approach decouples automation from container images, making execution order and failure modes explicit and auditable.
| Service | Role | Layer |
|---|---|---|
| Nginx | Reverse proxy and static asset handling. | Presentation |
| WordPress | Application logic execution via PHP-FPM. | Application |
| Database | Persistent data storage (MySQL) via named volumes. | Data |
Initialization (wp-init) |
One-shot site URL detection and synchronization. | Ops Plane |
Data Safety (db-backup) |
Automated snapshots and maintenance of the FIFO backup policy. | Ops Plane |
| CLIs | Stateless interfaces for manual maintenance (wp-cli, db-cli). |
Ops Plane |
Some design choices are intentionally opinionated to favor maintainability:
-
Explicit automation over implicit behavior
Initialization and migration logic is explicit in scripts, avoiding hidden behavior in entrypoints. -
Separation of lifecycle phases
Runtime services and operational tooling are isolated to prevent cross-responsibility coupling. -
Configuration as data
All behavior is driven by environment variables, keeping scripts generic and reusable.
These decisions directly support the workflows described earlier and aim to keep the system predictable as complexity grows.
To preserve consistency, the repository includes a CI pipeline (GitHub Actions) that validates:
-
Shell scripts
Linted to enforce correctness and portability. -
Docker Compose and YAML files
Validated for syntax and structural correctness. -
Makefile targets
Checked for consistency and common pitfalls. -
Markdown documentation
Optionally linted to enforce formatting and readability standards.
The stack is intentionally focused on development and operational workflows, while its structure is designed to support future extensions.
Additional Docker Compose layers (e.g. production-specific overrides) can be introduced to adapt runtime configuration, persistence, and networking concerns without modifying the core automation logic.
This approach allows the project to evolve incrementally as requirements grow.
Contributions are welcome. Please ensure that all changes pass the CI pipeline and follow the established architectural patterns.