Every WordPress developer eventually faces this choice: when you need a local dev environment, do you reach for Local WP (the friendly desktop app from Flywheel / WP Engine) or for a Docker-based setup?
“Docker” is a broad category here. It covers a whole family of WordPress dev tools — wp-env, DDEV, DevKinsta, Lando, or rolling your own docker-compose.yml. They all share the same core idea: WordPress runs inside isolated containers instead of as native processes on your host OS. And they share the same tradeoffs versus Local WP.
I’ve used both approaches for years. The answer isn’t “one is better” — they solve different problems. Pick the wrong one and you’ll fight your tooling. Pick the right one and the work just flows.
Short answer: Local WP for hands-on development and client sites; Docker for plugin/theme development and automated testing. Which specific Docker flavor you pick is a secondary choice I’ll come back to later in the post.
What each approach actually is
Local WP is a desktop GUI. You click “New Site”, it provisions a sandboxed WordPress installation on your machine, gives you a yoursite.local domain, handles SSL certificates, lets you pick PHP and MySQL versions from a dropdown, and leaves it running until you stop it. Free for developers. Architecturally, it runs WordPress on your host OS via native processes, with a light management wrapper around Nginx/MySQL.
Docker is a container platform. WordPress runs inside isolated containers (MySQL in one, PHP+Apache in another, sometimes a separate “tests” container for PHPUnit). You rarely interact with Docker directly for WordPress — instead, you use a higher-level tool that sits on top of Docker:
- wp-env — a CLI tool from the WordPress core team (
@wordpress/envon npm). Minimal config, plugin/theme focused, ships a pre-wired PHPUnit test environment. - DDEV — a full-featured Docker dev environment. Command-driven, flexible, supports many PHP frameworks, handles multi-project workflows.
- DevKinsta — free desktop GUI from Kinsta. Similar UX to Local WP, but Docker under the hood. Works regardless of where you host.
- Lando — flexible Docker-Compose wrapper, popular at agencies that use Lando across non-WP projects too.
- Raw docker-compose.yml — maximum control, most work. Rarely the right choice unless you have highly specific needs.
Each of these is a Docker-based option with its own tradeoffs. My default for plugin development is wp-env (zero-config PHPUnit out of the box), and most of the concrete examples below will use it. But the Docker-vs-Local-WP tradeoffs apply regardless of which Docker tool you pick.
When I reach for Local WP
1. Client work. Building a site for someone? Local WP gives you a real browsable site at clientname.local, stable URLs, persistent state, and a database that doesn’t vanish between sessions. You can run a handful of client sites side by side and switch between them from the tray icon.
2. Exploratory WordPress work. Evaluating a new theme, kicking the tires on a plugin, learning how a specific WordPress API behaves — Local WP’s polished GUI (one-click SSL, built-in Mailhog for email capture, Live Link for showing clients a work-in-progress) just works. No JSON config to write, no Docker daemon to start.
3. Debugging a production-shaped install. Reproducing a client’s exact WordPress + plugin + theme stack to chase a bug? Local WP’s “Push / Pull” cloud workflows (via WP Engine or Flywheel) make that almost trivial.
4. You don’t want Docker in your life. Some developers don’t want the Docker tax — the daemon memory overhead, the image-pull latency, the occasional “why isn’t this container responding.” Local WP respects that. It ships as a single installer and works.
When I reach for Docker
1. Plugin and theme development with automated tests. This is where Docker approaches shine — especially wp-env, which ships a pre-wired tests-cli container that runs PHPUnit against a separate WordPress test database. That’s the standard WordPress core testing stack, but you don’t have to build it yourself.
The loop looks like this:
npm run env:start # boots WordPress + MySQL + tests-cli containers
npm run env:test # runs PHPUnit against the WordPress test site
Compare to setting up wp-phpunit manually against Local WP: install MySQL separately, create a test database, write a wp-tests-config.php, wire up a PHPUnit bootstrap that loads WordPress correctly, make sure test fixtures clean up properly between tests. Several hours of fragile setup. wp-env collapses all of that into npm run env:start. DDEV has a similar story with its ddev phpunit command — different syntax, same payoff.
2. CI pipelines. This is where Local WP falls apart completely. Local WP is a desktop GUI app — you can’t run it on a GitHub Actions runner or a Linux container. Docker, by contrast, is the standard way to run anything in CI. Your plugin’s integration tests run identically on your laptop and in GitHub Actions. That matters more than you’d think; plugins that “pass on my machine” and break in CI are a daily occurrence.
3. Reproducible environments across a team. Commit .wp-env.json (or .ddev/config.yaml, or docker-compose.yml) to your repo. Every developer who clones the repo gets the exact same WordPress version, PHP version, pre-installed plugins, and test database. Local WP’s site config is per-machine — it drifts over time as different team members change things.
4. Throwaway development. Testing whether your plugin works cleanly on WordPress 6.3, 6.4, 6.5, and trunk? npm run env:destroy (wp-env) or ddev delete (DDEV) nukes everything. Switch the WordPress core ref, start fresh, test, destroy. Local WP installations persist and accumulate cruft — which is exactly what you want for client work, and exactly what you don’t want when you’re running a test matrix.
5. Pinning to specific WordPress or PHP versions. wp-env’s .wp-env.json accepts any Git ref:
{
"core": "WordPress/WordPress#6.5",
"phpVersion": "8.1",
"plugins": [ "." ]
}
Flip the tag, re-run, and you’re testing against a different WordPress version. Useful for compatibility matrices in WordPress.org plugin development. DDEV supports the same via config, with more knobs.
Which Docker tool should you actually pick?
If you’ve decided Docker is the right approach, here’s my rough guide to picking among the options:
- wp-env — default for plugin and theme development. Zero config to get started. Pre-wired PHPUnit. Built by the WordPress core team, so it tracks WordPress conventions closely. Ideal for anything you’ll distribute on WordPress.org. This is what I use on almost every plugin I maintain.
- DDEV — default for agencies and teams managing multiple WordPress projects. More flexible than wp-env (can configure custom services, add Redis/Elasticsearch, run complex multi-site setups). Also supports many non-WP frameworks if your agency does Laravel / Drupal work too.
- DevKinsta — default if you want Local WP’s GUI experience but with Docker under the hood, and you’re OK with Kinsta’s branding. Free, fully-featured GUI, works with any host. Worth trying if you bounce off Local WP because of the native-process quirks but don’t want to live in the CLI.
- Lando — if your team already uses Lando for non-WP projects. Otherwise DDEV covers the same ground with a better WP-specific story.
- Raw docker-compose.yml — only when you have highly specific requirements none of the above handle. I’ve done this once; I wouldn’t recommend it unless you know exactly why.
Most plugin developers should start with wp-env and move to DDEV only if they hit its limits. I haven’t hit wp-env’s limits yet.
Why it’s not either/or
Here’s the thing — you can, and probably should, use both approaches:
- Local WP for sites you want to live with. Client dev, a personal staging site, exploratory installs where you care that the WordPress is still there tomorrow.
- Docker for plugins and themes you’re building. Especially anything you plan to distribute. Plugin developers need the automated test infrastructure.
A bonus worth noting: wp-env also exposes a regular dev WordPress at http://localhost:8888 while it’s running. So if you’re building a plugin and want to “just click around and see it work,” wp-env covers that too — no need to also fire up Local WP for the specific plugin you’re currently building.
A real example: Docker in a plugin I’m building right now
I’m currently building a plugin called Content Ops — bulk operations for WordPress and WooCommerce, designed to work well with AI agents (Claude Code, MCP clients, etc.). It has two test layers, and the boundary between them maps cleanly to the Local WP / Docker question.
Unit tests use Brain Monkey and PHPUnit. Brain Monkey stubs WordPress functions, so WordPress isn’t actually loaded — the tests verify pure logic. They run in ~0.03 seconds. I run these constantly while coding. No Docker required at all.
composer test:unit
# OK (6 tests, 10 assertions)
# Time: 00:00.027
Integration tests use wp-phpunit + wp-env (the Docker-based option). They run against a real WordPress installation in Docker containers. They prove the plugin actually activates, its hooks fire, its custom tables get created, its REST endpoints respond. ~5–10 seconds per run.
The setup is literally this much code:
// .wp-env.json
{
"core": "WordPress/WordPress#6.5",
"phpVersion": "7.4",
"plugins": [ "." ],
"env": {
"tests": {
"mappings": {
"wp-content/plugins/content-ops": "."
}
}
}
}
// package.json (relevant scripts)
{
"scripts": {
"env:start": "wp-env start",
"env:test": "wp-env run tests-cli --env-cwd=wp-content/plugins/content-ops composer test:integration"
}
}
The first npm run env:start pulls Docker images — in my testing that took about four minutes on a typical home connection. After that, the test loop is fast. The containers start in seconds; tests run in seconds.
For GitHub Actions CI, the same two commands work unmodified:
- run: npm ci
- run: npm run env:start
- run: npm run env:test
If I were using Local WP instead, I’d be writing a custom PHPUnit bootstrap, hardcoding connection strings to a specific Local WP site, and trying to figure out how to make CI work — which would be impossible, because Local WP can’t run on a headless Linux runner. The Docker approach is just easier, and it scales from a solo side project all the way up to a widely-distributed plugin without changing the tooling.
Decision table
| You want to… | Use |
|---|---|
| Build a client site and keep it around | Local WP |
| Explore WordPress, evaluate plugins, click around | Local WP |
| Reproduce a production site’s exact stack | Local WP |
| Avoid Docker entirely | Local WP |
| Develop a plugin or theme | Docker (wp-env or DDEV) |
| Write PHPUnit tests that hit real WordPress | Docker |
| Run tests in CI | Docker |
| Test a matrix of WordPress/PHP versions | Docker |
| Share a reproducible dev environment with a team | Docker |
A note on the overhead
Docker has a reputation for being heavy. On Apple Silicon Macs with Docker Desktop, the overhead is real but manageable — I run wp-env on an M-series Mac with 16 GB and it’s fine. If you’re on 8 GB and already tight on memory, Local WP is gentler on your system.
When I’m not running integration tests, I quit Docker Desktop to reclaim the memory. npm run env:start spins the daemon back up next time I need it. That’s a perfectly fine workflow.
Conclusion
Local WP is a wonderful product — don’t read this as a knock on it. It’s the right tool when the job is “have a WordPress site that exists on my machine and will still be there next week.”
But for plugin and theme development with automated tests — especially anything you plan to ship to WordPress.org or distribute commercially — Docker (via wp-env, DDEV, or whichever flavor suits you) is built for the job. The start → test loop is one of the better developer experiences in the WordPress ecosystem, and it works the same on your laptop as it does in CI.
If you’re a plugin developer and you haven’t tried wp-env yet, spend a morning with it. You’ll never go back to hand-rolled PHPUnit bootstrap files.
Further reading
- Local WP — Flywheel’s desktop app
@wordpress/envon npm — the WordPress core team’s CLI tool- DDEV — full-featured Docker dev environment
- DevKinsta — free Docker-based GUI alternative to Local WP
- Lando — Docker Compose wrapper
- wp-phpunit on Packagist — the PHPUnit bridge most of these tools use under the hood

Leave a Reply