This is the comprehensive documentation for the PHP WordPress Stack. This documentation covers the architecture, setup, and custom automation tools we've built to ensure a "Plug-and-Play" experience across both macOS and Ubuntu 24.04.
A high-performance, developer-friendly Docker stack designed for local WordPress development. It uses PHP-FPM Alpine, Nginx, MariaDB, and Redis, with automated SSL and project management.
- Engine: PHP 8.3 FPM (Alpine Linux)
- Web Server: Nginx (with automated proxy support)
- Database: MariaDB 11.4
- Cache: Redis 7 (Alpine)
- Mail: Mailpit (SMTP capture for testing)
- Tools: WP-CLI,
mkcert(Local SSL), Custom Bash Management Scripts.
- Docker & Docker Compose
- mkcert:
brew install mkcert(Mac) orsudo apt install mkcert(Ubuntu). Runmkcert -installonce. - Local DNS: Ensure your
HOST_NAMEis in/etc/hostspointing to127.0.0.1.
Clone a project and create your .env file:
cp sample.env .env
Key variables to define:
CONTAINER_PREFIX: Unique prefix for the project (e.g.,wp_).HOST_NAME: Your local domain (e.g.,my-site.local).WORDPRESS_IMAGE_VERSION: Usually6.8-fpm-alpine.
Run the gcert script inside the project folder:
gcert
This generates trusted certificates in ./config/ssl/ based on your .env domain.
docker compose up -d
The stack will automatically detect an empty ./app folder and populate it with WordPress core files.
To maintain a consistent workflow, we use the following global scripts. Place these in /usr/local/bin/.
Manages projects via a central registry (~/.registry).
- Usage:
container [alias] [start|stop|restart|logs] - Example:
container my_site start - Why: It finds the folder automatically, runs compose, and opens the browser.
Reads your .env and generates certificates.
- Usage: Run
gcertinside any project folder. - Logic: Creates
local-cert.pemandlocal-key.peminside./config/ssl/.
Downgrades or updates WordPress without touching wp-content.
- Usage:
wp-version 6.2.2 - Logic: Surgically replaces
wp-adminandwp-includesto match the specific version.
This stack is optimized for Linux native Docker. To avoid "Permission Denied" errors while keeping files editable:
- UID Synchronization: The
Dockerfileis configured to map the internalwww-datauser to UID1000. - File Ownership: If you see "Forbidden" errors, run:
sudo chown -R $USER:$USER app/
Since the container user and your Ubuntu user share the same ID (1000), both can now read/write simultaneously.
.
├── app/ # WordPress Source Code (Volume)
├── config/
│ ├── php/ # Custom .ini files (uploads, mail, redis)
│ ├── nginx/ # Nginx templates and config
│ ├── ssl/ # Generated SSL certificates
│ └── Dockerfile # Custom PHP-FPM Image
├── .env # Project Configuration
└── compose.yml # Docker Orchestration
Accessing WP-CLI:
docker exec -it [prefix]app wp --info
Viewing Mailpit (Captured Emails):
Open https://mail.yourdomain.local in your browser.
Cleaning up Docker (Idle resources):
docker system prune -a
Reloading Nginx config without restart:
docker exec [prefix]server nginx -s reload
- Always use the Registry: Add your project to
~/.registryto use thecontainershortcuts. - Don't Edit Core: Keep all custom logic in
wp-content. - Environment Variables: If a script needs a database password, read it from the environment (
$WORDPRESS_DB_PASSWORD) rather than hardcoding it.