A complete sudo docker compose configuration for running WordPress with MySQL, Nginx reverse proxy, and automatic SSL certificates via Let's Encrypt.
- WordPress: Latest version with PHP-FPM
- MySQL 8.0: Database backend
- Nginx: Reverse proxy with HTTP/2 and SSL
- Let's Encrypt: Free SSL certificates via Certbot
- Security Headers: HSTS, X-Frame-Options, etc.
- Automatic Redirects: HTTP to HTTPS
- Optimized Caching: Static file caching rules
- Easy Renewal: Automated SSL certificate renewal
- Custom Themes & Plugins: Local volume mappings for easy development and management
- Docker and sudo docker compose installed
- Domain name pointing to your server
- Ports 80 and 443 open in firewall
- Root or sudo access
Ensure you have all these files in your directory:
.
├── sudo docker compose.yml
├── .env.example
├── setup.sh
├── renewal.sh
├── themes/ # Custom WordPress themes
├── plugins/ # Custom WordPress plugins
└── nginx/
└── conf.d/
├── wordpress-http.conf
└── wordpress-https.conf.template
cp .env.example .env
nano .envEdit the following values:
MYSQL_ROOT_PASSWORD: Strong root password for MySQLMYSQL_DATABASE: Database name (default: wordpress_db)MYSQL_USER: Database user (default: wordpress_user)MYSQL_PASSWORD: Strong password for database userDOMAIN: Your domain name (e.g., example.com)SSL_EMAIL: Your email for Let's Encrypt notifications
Make sure your domain's DNS A record points to your server's IP address:
example.com→ Your Server IP
chmod +x setup.sh
sudo ./setup.shThe script will:
- Create necessary Docker volumes
- Start MySQL, WordPress, and Nginx
- Request SSL certificates from Let's Encrypt
- Configure HTTPS
Visit https://yourdomain.com and follow the WordPress installation wizard.
If you prefer manual setup:
# Start database and WordPress first
sudo sudo docker compose up -d db wordpress nginx
### Obtain SSL Certificate
```bash
# Request certificate
sudo sudo docker compose run --rm certbot
# If successful, enable HTTPS configuration
cp nginx/conf.d/wordpress-https.conf.template nginx/conf.d/wordpress-https.conf
# Update domain in the config
sed -i 's/yourdomain.com/your-actual-domain.com/g' nginx/conf.d/wordpress-https.conf
# Restart Nginx
sudo sudo docker compose restart nginxLet's Encrypt certificates expire after 90 days. Set up automatic renewal:
chmod +x renewal.sh
# Add to crontab (runs twice daily at midnight and noon)
sudo crontab -e
# Add this line:
0 0,12 * * * /path/to/your/wordpress/renewal.sh >> /var/log/certbot-renewal.log 2>&1sudo sudo docker compose run --rm certbot renew
sudo sudo docker compose restart nginx# All services
sudo docker compose logs -f
# Specific service
sudo docker compose logs -f wordpress
sudo docker compose logs -f nginx
sudo docker compose logs -f db# All services
sudo docker compose restart
# Specific service
sudo docker compose restart nginxsudo docker compose down# Export database
sudo docker compose exec db mysqldump -u wordpress_user -p wordpress_db > backup.sql
# Or use root user
sudo docker compose exec db mysqldump -u root -p wordpress_db > backup.sqlsudo docker compose exec -T db mysql -u wordpress_user -p wordpress_db < backup.sqlsudo docker compose pull wordpress
sudo docker compose up -d wordpressThis setup includes volume mappings for custom themes and plugins, allowing you to develop and manage them directly on your host machine.
- Place your theme folder in the
themes/directory - Your theme will automatically appear in WordPress admin under Appearance → Themes
- Changes made to theme files are immediately reflected (may need to clear cache)
Example:
# Add a custom theme
cp -r my-custom-theme/ themes/
# Your theme is now available at:
# /var/www/html/wp-content/themes/my-custom-theme- Place your plugin folder in the
plugins/directory - Your plugin will automatically appear in WordPress admin under Plugins
- Activate the plugin from the WordPress admin panel
Example:
# Add a custom plugin
cp -r my-custom-plugin/ plugins/
# Your plugin is now available at:
# /var/www/html/wp-content/plugins/my-custom-pluginThe volume mappings are bi-directional:
- Local → Container: Files added to
themes/orplugins/appear in WordPress - Container → Local: Themes/plugins installed via WordPress admin appear in local directories
- Live Updates: Edit files locally and see changes immediately (no container restart needed)
- Restart WordPress container if themes/plugins don't appear:
sudo docker compose restart wordpress - File permissions are managed by Docker automatically
- Any themes/plugins installed through WordPress admin will persist in these directories
/var/lib/docker/volumes/
├── wordpress_db_data/ # MySQL data
├── wordpress_wordpress_data/ # WordPress files
├── wordpress_certbot_data/ # Certbot challenge files
└── wordpress_letsencrypt_data/ # SSL certificates
Local directories (mounted as volumes):
├── themes/ # Custom WordPress themes (./themes → /var/www/html/wp-content/themes)
└── plugins/ # Custom WordPress plugins (./plugins → /var/www/html/wp-content/plugins)
- Listens on port 80
- Handles Let's Encrypt verification
- Redirects all traffic to HTTPS
- Listens on port 443 with HTTP/2
- SSL/TLS with modern security settings
- Security headers (HSTS, X-Frame-Options, etc.)
- Static file caching
- PHP-FPM connection to WordPress
- Upload size limit: 64MB
- Strong Passwords: Use strong, unique passwords in
.env - Keep Updated: Regularly update Docker images
- Firewall: Only allow ports 80, 443, and SSH
- Backups: Regular database and file backups
- WordPress Security: Install security plugins (Wordfence, etc.)
- File Permissions: WordPress files are read-only in Nginx
Problem: Certificate request fails
Solutions:
- Verify domain DNS points to your server:
dig +short yourdomain.com - Check ports 80 and 443 are open:
netstat -tuln | grep -E '80|443' - Check Nginx logs:
sudo docker compose logs nginx - Wait if rate-limited (5 failures per hour limit)
Problem: Error establishing database connection
Solutions:
- Check database is running:
sudo docker compose ps - Verify credentials in
.env - Check logs:
sudo docker compose logs db - Restart services:
sudo docker compose restart
Problem: File upload fails
Solutions:
- Check
client_max_body_sizein nginx config - Verify WordPress upload limits in PHP settings
- Check disk space:
df -h
Problem: Site is slow
Solutions:
- Install WordPress caching plugin (WP Super Cache, W3 Total Cache)
- Optimize database
- Consider adding Redis for object caching
- Monitor resource usage:
docker stats
Edit nginx/conf.d/wordpress-https.conf:
client_max_body_size 128M; # Increase from 64MEdit WordPress environment in sudo docker compose.yml:
WORDPRESS_CONFIG_EXTRA: |
define('WP_MEMORY_LIMIT', '256M');Add to sudo docker compose.yml:
redis:
image: redis:alpine
container_name: wordpress_redis
restart: always
networks:
- wordpress_networkInstall Redis Object Cache plugin in WordPress.
This configuration is provided as-is for use in your own projects.
For issues:
- Check the troubleshooting section
- Review Docker logs
- Verify configuration files
- Check official documentation for each component