Custom WordPress Docker image based on the official WordPress image, enhanced with:
- Postfix mail relay support with OpenDKIM signing
- PHP Calendar extension
- Security hardening (Apache / PHP version exposure disabled)
The build script uses Docker Buildx to create multi-platform images that work on both Intel/AMD (x86_64) and ARM (Apple Silicon M1/M2/M3, ARM servers) architectures.
- The build script pulls the official
wordpress:php{VERSION}-apacheimage for your specified PHP version - It automatically detects the WordPress version from
/usr/src/wordpress/wp-includes/version.phpin that base image - It builds your custom image with postfix and PHP calendar
- It tags your image with 8 different tags matching the WordPress version scheme
This ensures your images always match the WordPress versions from the official images.
Note: Different PHP versions may have different WordPress versions. For example:
- PHP 7.4 might use WordPress 6.1.1 (last version supporting PHP 7.4)
- PHP 8.3/8.4 might use WordPress 6.8.3 (latest version)
Ensure Docker Buildx is available (included in Docker Desktop and recent Docker Engine versions):
docker buildx versionEach build creates 8 tags per PHP version, following the official WordPress image naming convention.
WordPress version is automatically detected from the base wordpress:php{VERSION}-apache image.
For example, building PHP 8.3 (which uses wordpress:php8.3-apache as the base) automatically detects the WordPress version and creates:
6.8.3-php8.3-apache(full version with Apache)6.8-php8.3-apache(minor version with Apache)6-php8.3-apache(major version with Apache)php8.3-apache(PHP version only with Apache)6.8.3-php8.3(full version)6.8-php8.3(minor version)6-php8.3(major version)php8.3(PHP version only)
# Build with default settings (PHP 8.3, WordPress auto-detected)
./build.sh 8.3
# Build with custom image name
./build.sh 8.3 myrepo/wordpress
# Build and push to Docker Hub or registry
./build.sh 8.3 myrepo/wordpress --push
# Build and load locally (single platform only)
./build.sh 8.3 myrepo/wordpress --load# Build all PHP versions (WordPress versions auto-detected for each)
./build.sh all myrepo/wordpress
# Build all versions and push to registry
./build.sh all myrepo/wordpress --pushThis creates 8 tags for each PHP version (7.4, 8.3, 8.4).
Each image supports both linux/amd64 and linux/arm64 platforms.
| Option | Description |
|---|---|
--push |
Build and push images to Docker registry (required for multi-platform) |
--load |
Build and load into local Docker (single platform only, uses current architecture) |
| (none) | Build only, stores in buildx cache but not in local Docker images |
Note: Multi-platform images cannot be loaded directly into Docker. Use --push to push to a registry, or --load for local testing (single platform).
# Build single version
make build
make build PHP_VERSION=8.3
make build IMAGE_NAME=myrepo/wordpress
# Build and push
make push IMAGE_NAME=myrepo/wordpress
make push-all IMAGE_NAME=myrepo/wordpress
# Build and load locally
make load PHP_VERSION=8.4
# View all options
make help| Variable | Description | Required | Example |
|---|---|---|---|
MAIL_FROM_DOMAIN |
Mail domain for system and Postfix | Yes | yourdomain.com |
POSTFIX_RELAYHOST |
SMTP relay host and port | Yes | [smtp.gmail.com]:587 |
POSTFIX_SMTP_USERNAME |
SMTP username for authentication | No | user@example.com |
POSTFIX_SMTP_PASSWORD |
SMTP password for authentication | No | your-password |
| Variable | Description | Required | Example |
|---|---|---|---|
DKIM_SELECTOR |
DKIM selector name | No (enables DKIM if set) |
Note: When DKIM_SELECTOR is set, DKIM signing is automatically enabled. If keys don't exist, they will be generated on first start and the DNS record will be displayed in the logs.
All standard WordPress environment variables are supported. See the official WordPress image documentation.
On first startup with DKIM enabled, keys will be generated automatically. The DNS record will be displayed in the logs:
docker logs wordpress
# Output will include:
# ==========================================
# DKIM DNS Record
# ==========================================
# Add this TXT record to your DNS:
#
# wordpress._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
# "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." )
#
# ==========================================Copy the DNS record and add it to your domain's DNS settings.
To persist DKIM keys across container restarts, mount a volume:
docker run -d \
-v dkim_keys:/etc/opendkim/keys \
-e MAIL_FROM_DOMAIN=yourdomain.com \
-e DKIM_SELECTOR=wordpress \
myrepo/wordpress:php8.3-apachedocker run -d \
--name wordpress \
-p 8080:80 \
-v dkim_keys:/etc/opendkim/keys \
-e MAIL_FROM_DOMAIN='yourdomain.com' \
-e POSTFIX_RELAYHOST='[smtp.gmail.com]:587' \
-e POSTFIX_SMTP_USERNAME='your-email@gmail.com' \
-e POSTFIX_SMTP_PASSWORD='your-app-password' \
-e DKIM_SELECTOR='wordpress' \
-e WORDPRESS_DB_HOST=mysql:3306 \
-e WORDPRESS_DB_USER=wordpress \
-e WORDPRESS_DB_PASSWORD=wordpress \
-e WORDPRESS_DB_NAME=wordpress \
myrepo/wordpress:6.8.3-php8.3-apache
# Available tags:
# myrepo/wordpress:6.8-php8.3-apache
# myrepo/wordpress:6-php8.3-apache
# myrepo/wordpress:php8.3-apache
# myrepo/wordpress:6.8.3-php8.3
# myrepo/wordpress:php8.3services:
wordpress:
image: myrepo/wordpress:6.8.3-php8.3-apache
# Or use any tag: 6.8-php8.3-apache, 6-php8.3-apache, php8.3-apache, etc.
ports:
- "8080:80"
environment:
# WordPress database configuration
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress_db_password
WORDPRESS_DB_NAME: wordpress
# Mail configuration
MAIL_FROM_DOMAIN: 'yourdomain.com'
# DKIM configuration (optional)
DKIM_SELECTOR: 'wordpress'
# Postfix relay configuration
POSTFIX_RELAYHOST: '[smtp.gmail.com]:587'
POSTFIX_SMTP_USERNAME: 'your-email@gmail.com'
POSTFIX_SMTP_PASSWORD: 'your-app-password'
volumes:
- wordpress_data:/var/www/html
- dkim_keys:/etc/opendkim/keys
depends_on:
- db
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress_db_password
MYSQL_ROOT_PASSWORD: mysql_root_password
volumes:
- db_data:/var/lib/mysql
volumes:
wordpress_data:
dkim_keys:
db_data:POSTFIX_RELAYHOST='[smtp.gmail.com]:587'
POSTFIX_SMTP_USERNAME='your-email@gmail.com'
POSTFIX_SMTP_PASSWORD='your-app-password'Note: Use an App Password for Gmail.
POSTFIX_RELAYHOST='[smtp.sendgrid.net]:587'
POSTFIX_SMTP_USERNAME='apikey'
POSTFIX_SMTP_PASSWORD='your-sendgrid-api-key'POSTFIX_RELAYHOST='[email-smtp.us-east-1.amazonaws.com]:587'
POSTFIX_SMTP_USERNAME='your-smtp-username'
POSTFIX_SMTP_PASSWORD='your-smtp-password'POSTFIX_RELAYHOST='[smtp.mailgun.org]:587'
POSTFIX_SMTP_USERNAME='postmaster@your-domain.mailgun.org'
POSTFIX_SMTP_PASSWORD='your-mailgun-smtp-password'# View all logs (Apache + Postfix)
docker logs wordpress
# Follow logs in real-time
docker logs -f wordpress
# View last 100 lines
docker logs --tail 100 wordpress
# Filter for postfix logs only
docker logs wordpress 2>&1 | grep postfixPHP is configured to use Postfix for the mail() function.
# Enter the container
docker exec -it wordpress bash
# Send a test email via command line
echo "Test message body" | mail -s "Test Subject" recipient@example.com
# Test PHP mail function
php -r "mail('recipient@example.com', 'Test Subject', 'Test message from PHP');"
# Exit and view logs from outside the container
exit
docker logs -f wordpress
# You'll see postfix logs showing the email being sentWordPress will automatically use PHP's mail() function, which now routes through Postfix:
- Install a WordPress plugin like "WP Mail SMTP" or "Check Email"
- Send a test email from WordPress admin
- Check the Docker logs to see the email being processed by Postfix:
docker logs -f wordpress | grep postfix
This project follows the same license as the official WordPress Docker image.