A Docker-based local development environment for WordPress with Nginx, PHP-FPM, and MySQL.
- Nginx: Pre-configured with SSL support (via mkcert).
- PHP 8.3: Optimized for WordPress with Xdebug, GD (JPEG/WebP), and common extensions.
- MySQL 8.0: Persistent storage for your data.
- Local HTTPS: Seamless local development with trusted certificates.
- Xdebug 3: Step debugging from your IDE on port 9003.
- Easy Setup: Scripts to automate environment initialization and management.
- Docker and Docker Compose
- mkcert (for local SSL certificates)
lsof(usually pre-installed on Linux/macOS)
Clone the repository and run the setup script:
./site setupThe script will:
- Check for required tools.
- Interactively create a
.envfile from.env.template. - Build the Docker images.
- Download WordPress core files into the current directory.
- Create a
wp-config.phpconfigured to use the environment variables.
To start the containers and set up the local domain and certificates:
./site startThis will:
- Add the local domain (default:
wordpress.local) to your/etc/hosts. - Generate and install local SSL certificates.
- Start Nginx, PHP-FPM, and MySQL containers.
Your site will then be available at: https://wordpress.local
./site setup: Initialize the environment../site start: Start the environment../site stop: Stop all containers../site restart: Restart the environment../site rebuild: Rebuild Docker images from scratch (no cache)../site certs: Regenerate SSL certificates (e.g. aftermkcert -installor CA change)../site reset: Danger! Removes all WordPress files, databases, and local configurations to reset the project.
.
├── certs/ # Generated SSL certificates (not in git)
├── docker/
│ └── php/
│ └── xdebug.ini # Xdebug 3 configuration
├── docker-compose.yml # Docker service definitions
├── Dockerfile # PHP-FPM image definition
├── nginx.conf.template # Nginx configuration template
├── site # Project management script
├── db # Database import/export script
├── wp-config.php # WordPress configuration
└── ... (WordPress core files)
PHP includes Xdebug 3 for step debugging. Configuration is in docker/php/xdebug.ini:
| Setting | Value |
|---|---|
| Mode | debug |
| Client host | host.docker.internal |
| Client port | 9003 |
| Start with request | yes |
- Build the image (already done by
./site setup/./site rebuild):docker compose build php - Start the environment:
./site start - Configure your IDE to listen for Xdebug connections on port 9003.
- Load the site — breakpoints will be hit.
Changes to docker/php/xdebug.ini only need a PHP container restart (no rebuild):
docker compose restart phpTo disable Xdebug, comment out xdebug.mode in docker/php/xdebug.ini and restart PHP.
Local SSL certificates are generated using mkcert and stored in certs/. They're automatically installed during ./site start.
Regenerate leaf certificates (e.g. after mkcert -install, a new machine, or browser "Not secure" warnings):
./site certs # Removes old certs/, issues new ones, restarts nginx if running- Port Conflicts: If ports 80 or 443 are already in use, the
sitescript will notify you. - Permissions: The setup scripts attempt to handle ownership issues, but ensure you run them as your regular user (not with
sudo). - Xdebug not connecting: Verify
xdebug.modeis set (not empty), checkdocker compose logs phpfor errors, and ensure your IDE is listening on port 9003.
This is a Docker-based boilerplate for local WordPress development using Nginx, PHP 8.3-FPM, and MySQL 8.0. It includes Bash scripts to automate local SSL certificate generation (via mkcert), host entry management, and WordPress core initialization.
To enter the PHP container and run commands directly:
docker compose exec php bashWP-CLI can be run inside the PHP container. Example to check core version:
docker compose exec php ./wp-cli.phar core version --allow-rootTo enter the MySQL shell directly:
docker compose exec mysql mysql -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME}Use the ./db script to easily back up or restore your database:
Export database to SQL file:
./db export # Export to dump.sql (default)
./db export backup.sql # Export to backup.sqlImport database from SQL file:
./db import backup.sql # Import from backup.sql (requires confirmation)The script automatically starts the site if needed and uses credentials from your .env file.