How to Set Up a Custom WordPress Development Environment Locally with Docker

If you’ve ever wrestled with XAMPP, MAMP, or even the popular LocalWP, you know the pain: bloated installs, PHP version conflicts, mystery permission errors, and environments that behave differently on every machine. In 2026, serious WordPress developers are moving to a smarter approach: a local WordPress development environment powered by Docker.

In this tutorial, we’ll spin up a fully containerized WordPress dev stack in under 10 minutes. You’ll get a clean, reproducible workflow with database setup, volume mounts for instant file edits, and live theme reloading. Let’s dive in.

Why Docker Beats XAMPP, MAMP and Even LocalWP

Tools like LocalWP and XAMPP are popular for a reason: they’re easy to click through. But they hide complexity that comes back to bite you when your production server doesn’t match your local setup. Docker fixes this by giving you the exact environment your live site runs on.

Feature Docker LocalWP XAMPP/MAMP
Reproducible across machines Yes Partial No
Version control for environment Yes (docker-compose.yml) No No
Mirror production stack Yes Limited Rarely
Easy multi-site / multi-PHP Yes Yes Painful
Resource footprint Low Medium High
docker wordpress laptop

What You’ll Need Before Starting

  • Docker Desktop installed (Windows, macOS, or Linux)
  • A code editor (VS Code, PhpStorm, etc.)
  • Basic command line familiarity
  • About 10 minutes of your time

That’s it. No PHP install. No MySQL install. No Apache. Docker handles everything.

Step 1: Create Your Project Folder

Open your terminal and create a clean folder for your project:

mkdir my-wp-site && cd my-wp-site
mkdir -p wp-content/themes wp-content/plugins

We pre-create the wp-content subfolders so we can mount our themes and plugins as volumes for live editing.

Step 2: Write the docker-compose.yml File

This single file defines your entire local WordPress development environment. Create a file named docker-compose.yml in your project root:

services:
  db:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass
    volumes:
      - db_data:/var/lib/mysql

  wordpress:
    image: wordpress:6.7-php8.3-apache
    depends_on:
      - db
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DEBUG: 1
    volumes:
      - wp_data:/var/www/html
      - ./wp-content/themes:/var/www/html/wp-content/themes
      - ./wp-content/plugins:/var/www/html/wp-content/plugins

  phpmyadmin:
    image: phpmyadmin:latest
    depends_on:
      - db
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: rootpass

volumes:
  db_data:
  wp_data:

What’s happening here?

  • db: A MariaDB container holding your WordPress database
  • wordpress: WordPress with PHP 8.3 and Apache, mapped to localhost:8080
  • phpmyadmin: Optional GUI for the database at localhost:8081
  • Volume mounts: Your local themes and plugins folders sync directly into the container, so any code change is reflected instantly
docker wordpress laptop

Step 3: Launch Your Environment

From your project folder, run:

docker compose up -d

Docker will pull the images and start three containers. Once finished, open your browser and go to:

  • WordPress: http://localhost:8080
  • phpMyAdmin: http://localhost:8081

You’ll be greeted by the WordPress installer. Set your title, admin user, and password. You’re live, locally.

Step 4: Enable Live Theme Reloading

Because your themes folder is mounted as a volume, every change to a PHP, CSS or JS file is immediate. For true live reloading in the browser, add BrowserSync to your theme workflow.

Inside your custom theme folder, initialize a Node project:

cd wp-content/themes/my-theme
npm init -y
npm install --save-dev browser-sync

Add this script to your package.json:

"scripts": {
  "dev": "browser-sync start --proxy 'localhost:8080' --files '**/*.php, **/*.css, **/*.js'"
}

Then run:

npm run dev

BrowserSync opens a new tab (usually localhost:3000) that auto-refreshes the moment you save any theme file. Perfect for rapid theme development.

Step 5: Use WP-CLI Inside Docker

Need to run WP-CLI commands? You can execute them directly inside your container:

docker compose exec wordpress bash
# Inside the container:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp
wp --info --allow-root

Or use the dedicated wordpress:cli image as a sidecar service in your compose file if you prefer.

docker wordpress laptop

Step 6: Daily Workflow Commands

Action Command
Start environment docker compose up -d
Stop environment docker compose down
View logs docker compose logs -f wordpress
Reset everything docker compose down -v
Enter container shell docker compose exec wordpress bash

Bonus: Sharing With Your Team

The real magic? Commit your docker-compose.yml to Git. Any teammate can clone the repo, run docker compose up -d, and have the identical development environment in minutes. No more “works on my machine” tickets.

Common Pitfalls and How to Fix Them

  1. Port already in use: Change 8080:80 to 8888:80 if another service is blocking port 8080.
  2. Permission errors on Linux: Run sudo chown -R $USER:$USER wp-content on your host folder.
  3. Database connection refused: Wait a few seconds after first launch. MariaDB needs time to initialize.
  4. Slow file sync on Mac/Windows: Add :cached or :delegated to volume mounts for performance.

FAQ

Is Docker better than LocalWP for WordPress development?

For solo bloggers, LocalWP is simpler. For developers, agencies, and teams who need reproducibility and parity with production, Docker wins every time. You can version your environment, share it via Git, and match server stacks exactly.

Do I need to know Docker deeply to use this setup?

No. The docker-compose.yml file in this guide is copy-paste ready. You only need to know three commands: up, down, and logs.

Can I run multiple WordPress sites at the same time?

Yes. Just create separate folders, each with its own docker-compose.yml, and assign different ports (e.g., 8080, 8082, 8084). They run in parallel without conflict.

How do I migrate my local Docker site to production?

Export your database with WP-CLI or phpMyAdmin, zip your wp-content folder, and upload both to your live server. Plugins like WP Migrate or All-in-One WP Migration also work flawlessly with this setup.

Does this work on Apple Silicon (M1/M2/M3) Macs?

Yes. The official WordPress and MariaDB images are multi-arch, so they run natively on ARM. No emulation tricks needed in 2026.

Final Thoughts

A Docker-based local WordPress development environment gives you something no point-and-click tool can: total control, perfect reproducibility, and a setup that mirrors your production server. Once you make the switch, you won’t go back to XAMPP or MAMP, and even LocalWP starts to feel limiting.

Save the compose file, commit it to your repo, and ship better WordPress sites faster. Happy coding.