Tech

WordPress Theme and Plugin Development with Docker

WordPress Theme and Plugin Development with Docker

One of the things I have always wanted was a simple, reliable and fast way to develop WordPress themes and plugins locally.

Over the years, I have tried LocalWP, XAMPP, MAMP, Laragon, WAMP, and manually installing PHP, MySQL, Apache and WP-CLI. They all work, but each option comes with its own trade-offs.

Some require several dependencies to be installed on your computer. Some behave differently depending on the operating system. Some are difficult to share with other developers. Occasionally, you can spend more time setting up the development environment than actually building the website.

I wanted something different.

I wanted a development environment that:

  • Works on Windows, macOS and Linux.
  • Only requires Docker Desktop or Docker Engine.
  • Does not require PHP, MySQL, Composer or WP-CLI to be installed on the host computer.
  • Can be stopped, deleted and recreated when needed.
  • Runs quickly on macOS and Windows.
  • Automates the initial WordPress installation.
  • Lets me immediately start developing themes and plugins.

After experimenting with a basic WordPress Docker Compose setup and gradually improving it, I created this WordPress Theme and Plugin Development Docker Starter.

The goal is to make local WordPress development approachable, even if you are not very familiar with Docker.

What Is Docker?

You do not need to understand every part of Docker before using this starter.

A simple way to think about Docker is as a portable, isolated environment that contains everything WordPress needs to run.

Instead of installing all of the following directly on your computer:

  • PHP
  • Apache
  • MariaDB or MySQL
  • WP-CLI
  • A local email testing service

Docker runs them inside containers.

This keeps your computer cleaner, reduces version conflicts, and makes it easier to use the same development environment across different operating systems.

As long as Docker Desktop or Docker Engine is installed, the project should run in the same general way on Windows, macOS and Linux.

What This WordPress Docker Starter Includes

Although the setup is simple to use, quite a lot happens behind the scenes.

The starter includes:

  • An automated WordPress installation.
  • A MariaDB database.
  • A custom WordPress Docker image.
  • WP-CLI inside the WordPress container.
  • Mailpit for testing outgoing emails.
  • phpMyAdmin for inspecting and editing the database.
  • Targeted theme and plugin volume mounts for better performance.
  • Persistent Docker volumes for the database and uploads.

Automated WordPress Installation

Normally, a new WordPress site opens the familiar installation wizard.

You select a language, enter the site title, create an administrator account, choose a password and complete the installation.

That process is not difficult, but it becomes repetitive when you regularly create development environments.

This starter automates the initial setup.

The first time the environment starts, a custom entrypoint wrapper waits for WordPress and the database to become available. It then uses WP-CLI to:

  • Install WordPress.
  • Create the administrator account.
  • Set the site title.
  • Configure the site URL.
  • Activate the local development theme.

After a short wait, the site is ready to use without completing the WordPress installation wizard manually.

Safe and Repeatable Startup

The automated installation script is designed to be idempotent.

In simple terms, that means it is safe to run more than once.

Before attempting to install WordPress, the script checks whether WordPress is already installed.

If the database already contains an existing site, the setup step is skipped. This allows the containers to be stopped and restarted without overwriting the site or resetting the database.

This is particularly useful during normal development because you can close Docker at the end of the day and return to the same site later.

Faster Performance on macOS and Windows

One of the most important decisions in this starter is how the project folders are mounted into Docker.

Many WordPress Docker tutorials mount the entire wp-content directory from the host computer into the WordPress container.

That approach is easy to understand, but it can cause noticeable performance problems with Docker Desktop on macOS and Windows.

WordPress contains a large number of small files. Synchronising all of those files across the boundary between the host operating system and the Linux container can create significant filesystem latency.

Instead of mounting the entire wp-content directory, this starter only mounts the folders you are actively developing:

./my-theme
./plugins

This means your theme and plugin files remain directly accessible from your normal code editor, while WordPress core and other files stay inside Docker.

The uploads directory is stored in a named Docker volume rather than being broadly mounted to the host.

This approach provides several benefits:

  • WordPress core remains inside the faster Docker filesystem.
  • The WordPress dashboard generally feels more responsive.
  • Your theme files still update immediately when saved.
  • Your plugin files remain easy to edit from the host computer.
  • Uploaded media persists when containers are restarted.
  • The project directory is not filled with generated upload files.

Performance note: Avoiding a full wp-content bind mount is especially useful on macOS and Windows, where Docker Desktop filesystem sharing can be slower than native Linux filesystems.

Built-in WP-CLI

WP-CLI is the command-line interface for WordPress.

It allows you to manage many parts of a WordPress site without using the browser-based administration area.

For example, WP-CLI can be used to:

  • Install and activate plugins.
  • Activate themes.
  • Create users.
  • Update options.
  • Flush rewrite rules.
  • Export or import the database.
  • Run search-and-replace operations.

WP-CLI is installed directly in the custom WordPress Docker image, so it does not need to be installed on your computer.

To run a WP-CLI command, prepend it with:

docker compose exec wordpress wp

For example, to list the installed plugins:

docker compose exec wordpress wp plugin list --allow-root

To flush the WordPress rewrite rules:

docker compose exec wordpress wp rewrite flush --allow-root

To list the installed themes:

docker compose exec wordpress wp theme list --allow-root

The --allow-root flag is required because the WP-CLI command is being executed inside the container as the root user.

Local Email Testing with Mailpit

Testing WordPress emails locally can be inconvenient.

You may need to test:

  • Contact form submissions.
  • Password reset emails.
  • New user notifications.
  • WooCommerce order emails.
  • Plugin alerts.
  • Custom transactional emails.

Connecting a real SMTP service during local development is often unnecessary, and it introduces the risk of accidentally sending test messages to real email addresses.

This starter includes Mailpit to solve that problem.

The custom WordPress image installs mhsendmail and configures PHP’s sendmail_path. Outgoing PHP emails are intercepted and routed to the Mailpit container.

Mailpit provides a local browser interface where you can inspect the subject, sender, recipient, HTML content, plain-text content and headers of every test email.

Mailpit is available at:

http://localhost:8025

No Mailpit username or password is required in the default local setup.

phpMyAdmin Database Access

The starter also includes phpMyAdmin.

phpMyAdmin provides a browser-based interface for viewing and managing the MariaDB database used by WordPress.

It can be useful when you need to:

  • Inspect WordPress options.
  • Review plugin database tables.
  • Run an SQL query.
  • Check saved post metadata.
  • Export a database.
  • Inspect data created by a theme or plugin.

phpMyAdmin is available at:

http://localhost:8180

Use the following login details:

  • Username: root
  • Password: password

Important: These credentials are intended for a local development environment only. Do not reuse simple development credentials on a public or production website.

Project Structure

The project is intentionally kept small so it remains easy to understand and modify.

.
├── compose.yml
├── Dockerfile
├── docker-entrypoint-wrapper.sh
├── my-theme/
└── plugins/

compose.yml

The compose.yml file defines the services that make up the development environment.

These include:

  • WordPress
  • MariaDB
  • phpMyAdmin
  • Mailpit

It also defines the ports, environment variables, persistent volumes and folder mounts used by the project.

Dockerfile

The Dockerfile extends the official WordPress image.

It installs the additional tools required by the starter, including WP-CLI and mhsendmail.

By adding these tools to the image, the development environment remains self-contained. Developers do not need to install PHP, Composer, WP-CLI or an email testing utility directly on their computer.

docker-entrypoint-wrapper.sh

The docker-entrypoint-wrapper.sh file wraps the official WordPress Docker entrypoint.

The official entrypoint still performs its normal WordPress container setup. The wrapper then runs the automated installation logic in the background.

It waits for the required files and database connection, checks whether WordPress is already installed, and performs the initial setup when necessary.

A retry loop makes the process more reliable because the WordPress container may become available slightly before the database is ready to accept connections.

my-theme

The my-theme directory contains the active development theme.

Because this folder is mounted directly into the WordPress themes directory, changes made in your code editor become available inside WordPress immediately.

You can rename the theme and update the relevant configuration if you want to use the starter for a different project.

plugins

The plugins directory is used for custom plugin development.

You can place one or several custom plugin folders inside it. They will appear in the WordPress Plugins screen and can also be managed through WP-CLI.

Requirements

Before starting, you need:

  • Docker Desktop on Windows or macOS, or Docker Engine with Docker Compose on Linux.
  • A code editor such as Visual Studio Code, Cursor, PhpStorm or another editor of your choice.
  • The downloaded starter files.

You do not need to install PHP, Apache, MariaDB, Composer or WP-CLI separately.

Getting Started

1. Download and Extract the Starter

Download the ZIP file and extract it to a suitable development folder.

For example:

Projects/wordpress-docker-starter

2. Open a Terminal in the Project Folder

Open Terminal, PowerShell, Windows Terminal or the terminal built into your code editor.

Make sure the current directory contains the compose.yml file.

3. Start the Environment

Run:

docker compose up -d

The -d option starts the containers in detached mode, which means they continue running in the background.

Docker Compose will build the custom WordPress image automatically when it does not already exist.

If you later change the Dockerfile or another image build instruction, you can explicitly rebuild it with:

docker compose up -d --build

For normal day-to-day use, the shorter command is usually enough:

docker compose up -d

4. Wait for the Initial Setup

On the first run, allow a short amount of time for MariaDB to start and for the automated WordPress installation to finish.

The exact time depends on the computer and whether Docker needs to download the base images.

On later starts, the existing database is detected and the installation step is skipped.

5. Open the Development Site

The WordPress frontend is available at:

http://localhost:8080

The WordPress administration area is available at:

http://localhost:8080/wp-admin

Use the default local login details:

  • Username: admin
  • Password: password

Local Service Addresses

Service Address Login
WordPress frontend http://localhost:8080 Not required
WordPress admin http://localhost:8080/wp-admin admin / password
Mailpit http://localhost:8025 Not required
phpMyAdmin http://localhost:8180 root / password

Viewing Container Status

To see whether the containers are running, use:

docker compose ps

This displays the status and published ports for each service.

Viewing the Logs

If WordPress is not available immediately, you can inspect the combined logs with:

docker compose logs

To follow the logs in real time:

docker compose logs -f

To view only the WordPress container logs:

docker compose logs -f wordpress

Press Ctrl + C to stop following the logs. This does not stop the containers.

Stopping the Environment

To stop the running containers while keeping the database and uploads:

docker compose stop

When you are ready to continue working, start them again with:

docker compose start

You can also use:

docker compose up -d

That command will start any existing containers and create anything that is missing.

Removing the Containers but Keeping Your Data

To stop and remove the containers and network while keeping the named volumes:

docker compose down

Your database and uploaded media remain stored in Docker volumes.

The next time you run docker compose up -d, the containers will be recreated and connected to the existing data.

Completely Resetting the Environment

Sometimes you may want to return to a completely fresh WordPress installation.

To remove the containers and delete the named volumes, run:

docker compose down -v

This deletes the local WordPress database and uploaded media stored in Docker volumes.

Your theme and plugin source code remain on the host computer because those folders are part of the project directory.

Warning: The -v option permanently deletes the Docker volumes used by this project. Export or back up anything important before running it.

When Is the Build Flag Required?

For the first startup, this command should normally be sufficient:

docker compose up -d

Docker Compose builds the custom image if it does not already exist.

You generally only need the --build flag when:

  • You changed the Dockerfile.
  • You changed a file copied into the image during the build.
  • You want to force Docker to rebuild the custom image.

In those cases, run:

docker compose up -d --build

Why the Environment Is Self-Contained

One of the main goals of this starter is dependency isolation.

WP-CLI and the local mail routing utility are installed inside the WordPress image. MariaDB, Mailpit and phpMyAdmin run in their own containers.

This means the host computer does not need matching versions of PHP, MariaDB or WP-CLI.

It also makes the starter more portable. A project can be copied to another computer with Docker installed and started without recreating a complicated local software stack.

Who Is This Starter For?

This environment is intended for:

  • WordPress theme developers.
  • WordPress plugin developers.
  • Students learning WordPress development.
  • Freelancers who want repeatable local project environments.
  • Teams that want a consistent setup across operating systems.
  • Developers who prefer not to install PHP and database services directly on their computer.

It is designed for local development rather than production hosting.

Why I Built It This Way

There are many WordPress Docker examples available online, but a lot of them focus on demonstrating the smallest possible Docker Compose file.

That is useful for learning the basic concepts, but it does not always produce the most comfortable environment for everyday theme and plugin development.

I wanted something I could extract, open and start with a single command.

I also wanted to avoid repeatedly installing WordPress, configuring an email testing service, installing WP-CLI and waiting for a large wp-content mount to respond on Docker Desktop.

The result is still relatively small, but it includes the tools I regularly need:

  • Automated setup.
  • Persistent data.
  • Fast theme and plugin editing.
  • WP-CLI.
  • Email testing.
  • Database access.

Download the WordPress Docker Starter

The complete WordPress Theme and Plugin Development Docker Starter will be available as a ZIP file.

Download the WordPress Docker Starter

After downloading it:

    1. Extract the ZIP file.
    2. Open the folder in your code editor.
    3. Make sure Docker is running.
    4. Run docker compose up -d.
  1. Open http://localhost:8080.

That is all you need to get the local environment running.

You can then begin editing the included theme, create a new plugin, inspect the database through phpMyAdmin and test outgoing emails through Mailpit.

I hope this starter removes some of the repetitive setup work and makes WordPress theme and plugin development a little easier to begin.

Leave a reply

Loading comments…