Local WordPress development used to mean XAMPP, a lot of PATH headaches, and the occasional PHP version mismatch that would eat an afternoon. These days there are at least three decent options worth knowing about: wp-env, WordPress Studio, and a hand-rolled Docker Compose setup. I’ve used all three on different projects and they each have a distinct personality.
wp-env: the official Node-based option
wp-env ships as part of the Gutenberg tooling and is maintained by the WordPress core team. If you’re building blocks or plugins, it’s the obvious first choice – it creates a pair of WordPress installs (one for development, one for testing) and wires them up automatically.
Install it globally or per-project:
npm install -g @wordpress/env
# or locally
npm install --save-dev @wordpress/env
Then drop a .wp-env.json in your plugin or theme directory:
{
"core": "WordPress/WordPress#6.5",
"plugins": [ "." ],
"themes": [],
"config": {
"WP_DEBUG": true,
"WP_DEBUG_LOG": true
},
"port": 8888
}
Run wp-env start and you get WordPress at localhost:8888. The test environment lives at localhost:8889. Credentials are always admin / password – fine for local use.
What I like: zero fussing with Docker Compose files, built-in WP-CLI access via wp-env run cli wp ..., and it respects the wp-env.override.json pattern so you can have personal overrides without polluting the repo. What I don’t like: it’s opinionated about the directory structure, and if you’re working on a full site (not just a plugin), it can feel constraining. Documentation is at developer.wordpress.org.
WordPress Studio
WordPress Studio is a desktop GUI app from Automattic, released in 2024. Think of it as the spiritual successor to Local (by Flywheel) but leaner. You click “Add site”, give it a name, pick a PHP version, and it’s running in under a minute. No terminal required.
It’s good for: designers who need to test a theme, clients who want to poke around locally, or anyone who doesn’t want to maintain a Docker setup. For developers who live in the terminal, it’s fine but not particularly useful – you’ll end up opening a shell anyway to run WP-CLI or install Composer packages.
One practical limitation: Studio manages its own PHP and MySQL binaries, which means you can’t easily add PHP extensions or customize php.ini beyond what the UI exposes. If you need xdebug or a custom Redis object cache, Docker is a better fit.
Docker Compose: more setup, more control
I switched to Docker Compose for most client projects a couple of years back because it gives you a docker-compose.yml that lives in the repo and documents exactly what the environment looks like. New team member? docker compose up -d and they’re running.
Here’s a minimal but usable compose file for WordPress development:
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: wordpress
MYSQL_USER: wp
MYSQL_PASSWORD: wp
volumes:
- db_data:/var/lib/mysql
wordpress:
image: wordpress:6.5-php8.2-apache
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp
WORDPRESS_DB_PASSWORD: wp
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DEBUG: 1
volumes:
- ./wp-content:/var/www/html/wp-content
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
cli:
image: wordpress:cli-php8.2
depends_on:
- db
- wordpress
volumes:
- ./wp-content:/var/www/html/wp-content
entrypoint: wp
command: "--info"
volumes:
db_data:
The uploads.ini file handles the classic “max upload size” problem:
file_uploads = On
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600
Mount only wp-content rather than the entire WordPress root – it keeps the volume lean and avoids accidentally overwriting core files. WP-CLI runs as a separate service to avoid permission issues that crop up when you run it from inside the main container.
For Xdebug, add this to the wordpress service and rebuild:
wordpress:
build:
context: .
dockerfile: Dockerfile.dev
# Dockerfile.dev
FROM wordpress:6.5-php8.2-apache
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
COPY xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
Docker’s own docs on volumes and networking cover the edge cases well: docs.docker.com/storage/volumes.
A note on database persistence and resets
One thing that bites people new to container-based WordPress dev: when you run wp-env clean all or docker compose down -v, you lose the database. That’s usually intentional – you want a clean state for tests – but it can be surprising the first time it happens on a project where you’d spent an hour importing a client’s database and configuring plugins.
For wp-env, use wp-env stop and wp-env start to pause and resume without destroying state. For Docker Compose, docker compose down without the -v flag preserves the named volume. I’ve started keeping a make db-export target in client projects that runs:
docker compose exec db mysqldump -u wp -pwp wordpress > ./db/snapshot.sql
And a corresponding make db-import that loads it back. Adds five minutes to the initial setup and has saved me multiple times.
Syncing with a staging environment
Local dev is only useful if it resembles production. For most WordPress projects that means getting the production database down to local, with URLs replaced. wp-env and Docker Compose both give you WP-CLI access, so the standard approach works in either case:
# after importing the prod DB dump
wp search-replace 'https://client-site.com' 'http://localhost:8080' --skip-columns=guid
A few things to watch: the --skip-columns=guid flag is important – replacing GUIDs breaks WordPress attachment tracking. Also run wp cache flush after the replace, because some plugins (object cache, page cache) may have stale URLs stored.
If you’re working with WooCommerce or a plugin that stores serialized URLs in the database, add --precise to the search-replace command. The default regex-based replacement can corrupt serialized data.
Which one to pick
If you’re building a Gutenberg block or a plugin and want to run automated tests, use wp-env – it’s the path of least resistance and the tooling integrates cleanly with @wordpress/scripts. If you’re handing off a site to a non-developer or want something that just works with a double-click, WordPress Studio is hard to argue with. If you’re working on a production-grade site, collaborating with a team, or need precise control over the PHP configuration, Docker Compose is worth the initial setup cost.
My day-to-day is mostly Docker Compose with the wp-env config checked into plugin repos for CI. Studio I keep installed for the occasional “can you quickly check how this looks in WordPress” request. All three tools have improved noticeably over the last year – the gap between them is narrower than it used to be, which is a good problem to have.