If you want to run WordPress locally, skip XAMPP/MAMP and use Docker Compose. Here’s a setup that works for migrations, plugin/theme dev, or testing.

1. Prerequisites
- Docker and Docker Compose installed (
docker composeCLI should work) - Project folder (name it whatever you want)
2. The Compose File
Paste this as compose.yml in your project root:
services:
wordpress:
image: wordpress:6.5-php8.2-apache
container_name: wp_site
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppassword
WORDPRESS_TABLE_PREFIX: your_table_prefix_
WP_DEBUG: true
volumes:
- ./public_html:/var/www/html
depends_on:
- db
db:
image: mariadb:10.6
container_name: wp_db
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppassword
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Replace yourprefix_ with your table prefix (default is wp_).
Update passwords as needed.
3. Add Your Files
- New site: download WP core and put it in
public_html - Existing site: extract your
public_htmlfrom production here
You can also drop your database export (database.sql) in the root directory for later.
4. Start Containers
docker compose up -d
This will:
– Start WordPress at http://localhost:8080
– Start MariaDB for your WP instance
5. Import Database (if migrating)
Replace database.sql with your file name:
docker exec -i wp_db mysql -u wpuser -pwppassword wordpress < database.sql
6. Table Prefix
If your imported DB tables use a custom prefix (not wp_), set WORDPRESS_TABLE_PREFIX in your compose file (as above).
Otherwise, WordPress will act like it’s a fresh install.
7. URLs and Media
If you migrated from production, update all site URLs:
docker run --rm --network yourproject_default \
-v "$PWD/public_html:/var/www/html" \
-w /var/www/html \
-e WORDPRESS_DB_HOST=db \
-e WORDPRESS_DB_USER=wpuser \
-e WORDPRESS_DB_PASSWORD=wppassword \
-e WORDPRESS_DB_NAME=wordpress \
-e WORDPRESS_TABLE_PREFIX=yourprefix_ \
wordpress:cli \
php -d memory_limit=512M /usr/local/bin/wp search-replace 'https://yourproductiondomain.com' 'http://localhost:8080' --skip-columns=guid
Adjust network name, domain, and prefix as needed. Run the command twice, the first time as shown above and the second time remove the ‘http’ / ‘https’ from the url listed, since both forms exist in wordpress dbs.
8. Logging In
If your WP admin login doesn’t work after importing, reset the password with:
docker run --rm --network yourproject_default \
-v "$PWD/public_html:/var/www/html" \
-w /var/www/html \
-e WORDPRESS_DB_HOST=db \
-e WORDPRESS_DB_USER=wpuser \
-e WORDPRESS_DB_PASSWORD=wppassword \
-e WORDPRESS_DB_NAME=wordpress \
-e WORDPRESS_TABLE_PREFIX=yourprefix_ \
wordpress:cli \
php -d memory_limit=512M /usr/local/bin/wp user update youradmin --user_pass='yournewpass'
9. Done
Site is up at http://localhost:8080.
Debug as needed using WP_DEBUG or by checking logs.
No magic, no plugins required. If you break it, just blow away containers and volumes and start over.