WP Local Docker is an easy to use Docker based local development environment for WordPress development that works on Mac, Windows, and Linux.
Caution
As of 12 April 2024, this project is archived and no longer being actively maintained.
Note
Version 4 of WP Local Docker has been released and contains breaking changes.
Please follow the migration instructions when upgrading.
- Introduction
- Prerequisites
- Installation
- Using WP Local Docker
- Advanced Usage
- Tools
- F.A.Q
- Troubleshooting
- Migrating from Older Versions
WP Local Docker is an easy to use Docker based local development environment for WordPress development that works on Mac, Windows, and Linux. Any number of environments can be created and may run at the same time1, and requests will be routed appropriately to the correct environment based on the hostname specified during environment creation.
Each environment you create in WP Local Docker is powered by a couple of services you may already be familiar with:
- nginx: a high-performance HTTP server and reverse proxy,
- phpfpm: a fast and robust PHP FastCGI process manager,
- memcached: a distributed memory object caching system,
- elasticsearch (optional): a search and analytics engine.
You can choose to run your environment on different versions of PHP including 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1 or 8.2.
WP Local Docker comes with features that make managing your WordPress development a breeze:
- MySQL container: Handles all the MySQL databases across your environments,
- WP Snapshots: Allows you to easily create and use snapshots of your WordPress installation,
- PHPMyAdmin: Provides a user-friendly interface to manage your MySQL databases,
- mailcatcher: Catches any mail sent from your environments.
Lastly, WP Local Docker also takes care of downloading and installing WordPress for you. You can choose between a single site installation, a Multisite with Subdirectories, a Multisite with Subdomains, or the core development version.
WP Local Docker requires a few tools to function properly:
For the best experience, we recommend using the latest versions of Docker and Docker-compose. As for Node, the minimum supported version is Node 16. While WP Local Docker may work with other versions, we can't guarantee full compatibility. To manage Node versions, consider using NVM.
On a Mac? Great! You can get Docker Desktop from the Docker website. It comes with Docker-compose installed. For NodeJS and npm, you can install them from the NodeJS website, via a package manager like Homebrew, or using NVM.
Did you install Node from the NodeJS website? If so, you might encounter an EACCESS
error when trying to install global npm packages without using sudo. To prevent this, check out npm's guide on preventing permission errors. Or, you can simply run the install command with sudo.
If you're on Windows, you can download Docker Desktop from the Docker website. It also comes with Docker-compose. You can get NodeJS and npm from the NodeJS website. You may also need Python 3.7+ and Visual Studio 2015 or newer with the “Desktop development with C++” workload.
We recommend using the WSL/2 backend for Docker. You should use nvm to install Node inside of your default Linux distro. Once you have, you can install WP Local Docker, from inside of Linux, following the installation instructions.
It's useful to share git credentials between Windows and WSL/2. To do so, run the following commands inside of your default Linux distro, replacing USER-NAME
with your Windows username:
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager.exe"
cd ~/.ssh
cp /mnt/c/Users/USER-NAME/.ssh/id_rsa* .
If https is not working in the browsers on Windows, you will need to set up a shared root certificate. You will need mkcert installed inside your WSL2 machine. With mkcert
installed, run the following commands:
mkcert -CAROOT
That will output the path to a certificate root directory which contains the rootCA.pem
file you will need to share with Windows.
List the directory path you got from the previous command:
ls /home/<user>/.local/share/mkcert
If there is no such directory or the directory is empty run:
mkcert -install
You should see an output like this:
Created a new local CA 💥
The local CA is now installed in the system trust store! ⚡️
The local CA is now installed in the Firefox trust store (requires browser restart)! 🦊
If there was no root certificate initially, you will need to regenerate the certificates for all the sites:
10updocker cert generate <yourwebsite.test>
Now, there should be a rootCA.pem
file in the root certificate directory. Copy the rootCA.pem
into any directory on Windows. In the Windows PowerShell, set that directory as CAROOT
environment variable:
$Env:CAROOT = "C:\path\to\directory\with\certificate"
Then install certificate in the Windows PowerShell with:
mkcert -install
You may need to install mkcert
on Windows, or just use the latest executable from the releases page.
Remember to restart any open browsers for this change to take effect! This should fix any https issues.
For Linux users, Docker provides platform-specific installation instructions on their documentation site. Once Docker is installed, you will need to manually install Docker compose. You can install NodeJS via a package manager for many Linux platforms following these instructions. To setup C compilers & add a sudo user to the Docker group, run:
sudo apt install -y gcc make
sudo usermod -a -G docker user
Getting WP Local Docker up and running on your system involves a few simple steps. Start by ensuring that you have met all the prerequisites for installation.
Next, you can install WP Local Docker as a global npm package. Run the following command in your terminal:
npm install -g wp-local-docker
To confirm that WP Local Docker has been installed successfully, you can check its version. Simply type:
10updocker --version
The first time you use a WP Local Docker command, it will use default configuration settings. These settings include storing all your environments within the ~/wp-local-docker-sites
directory and managing your hosts file when creating and deleting environments.
If you want to customise the environment path or choose not to let WP Local Docker update your hosts file, you can do so. Run the command:
10updocker configure
Then, follow the prompts to customise your settings.
Keeping WP Local Docker up-to-date is important. To update it, you can run the installation command again. NPM will replace your current version with the latest one. Here's the command:
npm install -g wp-local-docker
Creating an environment in WP Local Docker is as simple as answering a series of prompts. To start, run the following command in your terminal:
10updocker create
You'll be guided through the process of configuring your environment to fit your needs.
We recommend using the .test
top-level domain (TLD) for your local environments. Why .test
? This TLD is reserved for software testing and won't be installed into the global Domain Name System. Plus, WP Local Docker is set up to direct any container-to-container traffic for .test
TLDs straight to the gateway container. This means features like WP Cron and the REST API will work between environments right out of the box.
To start a pre-existing environment, run the following command:
10updocker start <hostname>
Replace <hostname>
with the hostname of the environment you want to start.
Want to start all environments at once? We've got you covered! You can use a special hostname all
to start all environments and global services. Here's how:
10updocker start all
Sometimes, you might need to stop an environment from running. Don't worry, stopping an environment won't delete any files, Docker volumes, or databases related to that environment. All you need to do is run the following command:
10updocker stop <hostname>
Replace <hostname>
with the hostname of the environment you want to stop.
Just like with starting environments, you can stop all your running environments and global services at once using the special hostname all
. Here's the command:
10updocker stop all
The config/
directory of an environment is where you can find settings for various services. Here's what you'll find inside:
elasticsearch/
elasticsearch.yml
nginx/
default.conf
develop.conf
server.conf
php-fpm/
docker-php-ext-xdebug.ini
- This is where you'd put settings typically found in aphp.ini
file, likemax_execution_time
,memory_limit
,xdebug.max_nesting_level
,post_max_size
,upload_max_filesize
, and others.wp-cli.develop.yml
wp-cli.local.yml
Remember, after making changes to any files in the config/
directory or to the docker-compose.yml
file, you'll need to recreate the containers. You can find instructions on how to do this under Restart an Environment.
If you need to restart all services associated with a pre-existing environment, you can easily do so with the following command:
10updocker restart <hostname>
Remember to replace <hostname>
with the hostname of the environment you want to restart.
And yes, just like with starting and stopping environments, you can restart all your environments and global services at once using the special hostname all
. Here's how:
10updocker restart all
Keeping your environments updated with the latest features and improvements is important. With WP Local Docker, you can upgrade all services associated with a pre-existing environment using the following command:
10updocker upgrade <hostname>
Replace <hostname>
with the hostname of the environment you want to upgrade.
This command will help you keep your environments updated with the most recent changes from upstream.
If you created your environment before v2.6.0
, we recommend upgrading. You'll notice a significant performance increase.
For environments created before v3.0.1
, the upgrade will update the Elasticsearch image. Please note that when updating the Elasticsearch image, we need to delete the Docker volume, so you'll need to reindex after running this command.
There might be times when you need to delete an environment. To do this, run the following command:
10updocker delete <hostname>
Make sure to replace <hostname>
with the hostname of the environment you want to delete.
Please be aware that this action will permanently delete the environment, along with any local files, Docker volumes, and databases related to it.
If you need to delete all environments, you can use the special hostname all
. When you do this, you'll be asked to confirm the deletion of each environment:
10updocker delete all
Remember, deletion is permanent. So make sure you have everything backed up or moved before you delete an environment.
Working with SSL on your local environments? WP Local Docker has got you covered. Here's how you can manage your SSL certificates:
To generate certificates for a specific environment, use the following command:
10updocker cert generate <hostname>
Replace <hostname>
with the hostname of the environment you want to generate a certificate for.
If you need to install a new certificate authority in the system trust store, you can do so with this command:
10updocker cert install
Just follow the prompts, and you'll have your certificates managed in no time.
If you've enabled Elasticsearch for an environment, you can easily send requests from your host machine to the Elasticsearch server. How do you do this? Simply prefix the URL path with /__elasticsearch/
.
For example, if you wanted to access the /_all/_search/
endpoint of Elasticsearch, the URL would look like this:
http://<hostname>/__elasticsearch/_all/_search
Don't forget to replace <hostname>
with the hostname of your environment.
When configuring the ElasticPress settings, enter http://<hostname>/__elasticsearch
as the Elasticsearch host.
Running WP CLI commands against an environment is a breeze with WP Local Docker. Here's how you do it:
First, navigate to your environment directory. By default, this would be somewhere within ~/wp-local-docker-sites/<environment>/
. Replace <environment>
with the name of your environment.
Once you're inside the environment directory, you can run WP CLI commands using the following syntax:
10updocker wp <command>
Replace <command>
with any valid command you would usually pass directly to WP CLI.
Let's look at a couple of examples:
- To replace all instances of 'mysite.com' with 'mysite.test' in your database, run:
10updocker wp search-replace 'mysite.com' 'mysite.test'
- To list all sites in a multisite installation, use:
10updocker wp site list
And that's it! You can now run any WP CLI command against your WP Local Docker environment.
Did you know that you can get a shell inside any container in your environment? It's easy with WP Local Docker. Just use the following command:
10updocker shell [<service>]
Replace <service>
with the name of the service whose container you want to access. If you don't specify a service, WP Local Docker will use the phpfpm
container by default.
The available services can vary depending on the options you selected when creating the environment. However, they may include:
phpfpm
nginx
elasticsearch
memcached
This feature gives you a powerful tool for managing and troubleshooting your environments.
Keeping an eye on your container logs is a crucial part of managing your environments. With WP Local Docker, you can easily access real-time logs using the following command:
10updocker logs [<service>]
Replace <service>
with the name of the service whose logs you want to view. If you don't specify a service, WP Local Docker will show logs from all containers in the current environment.
To stop viewing the logs, just press ctrl+c
.
The available services can vary depending on the options you selected when creating the environment. However, they may include:
phpfpm
nginx
elasticsearch
memcached
With this command, you can keep track of what's happening in your environments at any given moment.
Cache helps speed up operations and save bandwidth for WP CLI, Snapshots, and npm (when building the development version of WordPress). But there might be times when you need to clear it.
To clear the WP CLI, WP Snapshots, and npm caches, simply run the following command:
10updocker cache clear
This command will help keep your environments running smoothly and efficiently.
Keeping your Docker images updated is essential for optimal performance and security. To update the Docker images used by WP Local Docker to the latest available version, use the following command:
10updocker image update
This command will check which Docker images are present on your system and update them as needed.
WP Local Docker uses a suite of global services to function properly. If you need to turn off these services, you can use the following command:
10updocker stop all
This command will stop all running environments followed by the global services.
phpMyAdmin is included in the global services stack deployed to support all environments.
You can access phpMyAdmin by navigating to http://localhost:8092.
Use the following credentials to log in:
- Username:
wordpress
- Password:
password
MailCatcher is included in the global services stack deployed to support all environments. It's preconfigured to catch mail sent from any of the environments created by WP Local Docker.
You can access MailCatcher by navigating to http://localhost:1080.
Make sure you are running the expected version by running:
php -v | grep Xdebug
The command needs to be executed on the docker image of PHP in order to get the right version of docker running on that container.
The command above would return an ouput like:
with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans
Update the configuration file on your site usually located at config/php-fpm/docker-php-ext-xdebug.ini
in order to
be updated to the new settings for Xdebug 3
.
xdebug.client_host = host.docker.internal
xdebug.mode = develop,debug
xdebug.start_with_request = yes
xdebug.output_dir = /var/www/html/wp-content
xdebug.log=/var/www/html/wp-content
Make sure to restart your docker image after this changes or stop / start. To verify your changes were applied you can create a file
called info.php
and add <?php phpinfo(); ?>
at the root of your project and then visit yourdomain.com/info.php
and look for
the values described above to verify your settings were actually applied, if that's not the case verify the path for your
xdebug.ini
file is actually placed into the right location.
Open the file docker-compose.yml
and update the line:
'./config/php-fpm/docker-php-ext-xdebug.ini:/etc/php.d/docker-php-ext-xdebug.ini:cached'
with: (For PHP7.4) specifically it might vary depdending on your PHP version.
'./config/php-fpm/docker-php-ext-xdebug.ini:/etc/php/7.4/fpm/conf.d/99-ext-xdebug.ini:cached'
Go to Settings > PHP > Debug
.
- Set the port to
9003
- Check (Ignore external connections through unregistered server configurations) to avoid wait on non wanted files.
- Check (Resolve breakpoint if it's not available on the current line)
- Uncheck (Force break at first line when no path mapping specified)
- Uncheck (Force break at frist line when a script is outside the project)
Go to Settings > PHP > Servers
.
-
Add a new server with the following settings:
name: yourdomain.com
host: localhost
port: 80
debugger: Xdebug
- Enable
Use path mappings (select if the server is remote or symlinks are used)
- Within the map directory select the path you want to debug (usually
wp-content
) and map it to/var/www/html/wp-content
-
Save your settings
-
Start to listen for connections on the top bar of your IDE (red phone icon)
- Ensure Xdebug is enabled for the environment using the
ENABLE_XDEBUG
environment variable. - Install the PHP Debug extension.
- In your project, go to the Debug view, click "Add Configuration..." and choose PHP environment. A new launch configuration will be created for you.
- Set the
pathMappings
parameter to your localwordpress
directory. Example:
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html": "${workspaceFolder}/wordpress",
}
}
]
Xdebug is included in the php images but must be manually enabled if you use wp-local-docker 2.7.0 or earlier. To enable Xdebug, set the environment variable ENABLE_XDEBUG
to 'true'
in the docker-compose.yml
file in the root of the project. If you use wp-local-docker 2.8.0 or higher, then new environments will have Xdebug enabled by default.
Make sure your IDE is listening for PHP debug connections and set up a path mapping to your local environment's wordpress/
directory to /var/www/html/
in the container.
- Ensure Xdebug is enabled for the environment using the
ENABLE_XDEBUG
environment variable. - Install the PHP Debug extension.
- In your project, go to the Debug view, click "Add Configuration..." and choose PHP environment. A new launch configuration will be created for you.
- Set the
pathMappings
parameter to your localwordpress
directory. Example:
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000,
"pathMappings": {
"/var/www/html": "${workspaceFolder}/wordpress",
}
}
]
Starting from version 4.0.0, WP Local Docker has switched from the old WP Snapshots system to the new Snapshots WP-CLI command. Although the public API and configuration have remained the same, the new system is more robust and allows for easier future feature additions.
If you haven't used Snapshots with WP Local Docker yet, you'll first need to configure Snapshots with your AWS credentials. To do so, run the following command:
10updocker wp snapshots configure <repository>
Replace <repository>
with your repository name (for example, 10updocker wp snapshots configure 10up
). You'll then be prompted to enter your AWS credentials and a few other configuration details. Once completed, the configuration will be available across all of your WP Local Docker environments.
To pull an existing snapshot from the repository into your current environment (replacing your database and wp-content), use the following command:
10updocker wp snapshots pull <snapshot-id>
Replace <snapshot-id>
with the ID of the snapshot you want to pull. Make sure to run this command from within your environment directory (by default, this is somewhere within ~/wp-local-docker-sites/<environment>/
).
To search the repository for snapshots, use the following command:
10updocker wp snapshots search <search-term>
Replace <search-term>
with the term you want to search for. The search term will be compared against project names and authors. If you search for "*", the command will return all snapshots.
The general form for all Snapshots commands is as follows:
10updocker wp snapshots <command>
Replace <command>
with any command that Snapshots accepts. The command is passed directly to Snapshots, so it will work with any Snapshots command. Note that any command requiring a WordPress environment (like pull, create, etc.) needs to be run from within an environment directory (by default, this is somewhere within ~/wp-local-docker-sites/<environment>/
).
Concurrent environments are limited by the available resources of your host machine.
See the Troubleshooting section.
One of the primary performance bottlenecks with Docker for Mac is file syncing between the host machine and the Docker containers. The less files that are mounted into the Docker container volumes, the less work Docker needs to do ensuring those files are synced. NPM and the /node_modules/ directories are the worst offenders by far. Since assets are transpiled/compiled from source prior to being used on the frontend, the dependencies in node_modules/
are not actually required to run the site locally, only the compiled dist files.
In order to mitigate the additional pressure node_modules/
puts on Docker filesystem syncing, we can instruct Docker to ignore directories when mounting volumes. Technically, we are instructing Docker to mount nothing to a specific path on the volume, but the effect is the same. See below for a practical example of how one might edit the docker-compose.yml
file in the site root:
nginx:
# ...
volumes:
- './wordpress:/var/www/html:cached'
- '/var/www/html/wp-content/themes/{my-theme}/node_modules'
- '/var/www/html/wp-content/plugins/{my-plugin}/node_modules'
phpfpm:
# ...
volumes:
- './wordpress:/var/www/html:cached'
- '/var/www/html/wp-content/themes/{my-theme}/node_modules'
- '/var/www/html/wp-content/plugins/{my-plugin}/node_modules'
Note: This action cannot be performed automatically as the specific paths to node_modules/
cannot be determined. You will need to manually determine the path where node_modules/
will be mounted onto the volume.
Once you have made the appropriate changes in your docker-compose.yml
file, you must stop and start for the changes to take effect and confirm things have worked.
To upgrade to a newer version of PHP, please edit the docker-compose.yml
file in the environment you are updating.
From:
phpfpm:
image: '10up/wp-php-fpm-dev:5.6-ubuntu'
# ...
volumes:
- './wordpress:/var/www/html:cached'
- './config/php-fpm/docker-php-ext-xdebug.ini:/etc/php.d/5.6/fpm/docker-php-ext-xdebug.ini:cached'
To:
phpfpm:
image: '10up/wp-php-fpm-dev:7.4-ubuntu'
# ...
volumes:
- './wordpress:/var/www/html:cached'
- './config/php-fpm/docker-php-ext-xdebug.ini:/etc/php.d/7.4/fpm/docker-php-ext-xdebug.ini:cached'
Once you update this run docker-compose down
and docker-compose up
to rebuild the containers.
While you could modify the port configuration globally or per project, this will require making adjustments in other areas to prevent a permissions error when starting up the database, such as:
Error: ER_ACCESS_DENIED_ERROR: Access denied for user 'root'@'localhost' (using password: YES)
For best results we recommend using the default port configuration whenever possible.
ngrok http -host-header=10up.test 80
For existing sites, if you wish to utilize the new M1 architecture optimized Docker images, you'll need to edit the docker-compose.yml
file to match a newly created one.
Alternatively, if you create new sites, they will be optimized for M1 architecture by default.
Facing issues with WP Local Docker? Here are a few steps you can follow to troubleshoot:
-
Update Docker and Node: First, make sure that Docker and Node are up to date.
-
Update wp-local-docker: Ensure that wp-local-docker is up to date as well. You can do this by running the following command:
npm i -g wp-local-docker
-
Restart Docker: Once everything is up to date, it's generally a good idea to restart Docker.
-
Update Docker images: Make sure you are using the latest Docker images by running the following command:
10updocker image update
- Reset global services configuration: Run the following command and answer
Yes
to the promptDo you want to reset your global services configuration? This will reset any customizations you have made.
:
10updocker configure
- Reset specific instance: Finally, if you're having issues with a specific instance, you can reset it by running the following command:
10updocker upgrade
This will replace the docker-compose.yml
file for that particular site instance.
Remember, troubleshooting is a process of elimination. Try these steps one by one to identify and resolve the issue.
If you are running something like MAMP or Laravel Valet on your Mac, it is possible you may have port conflicts when attempting to use wp-local-docker, such as:
Cannot start service mysql: Ports are not available: listen tcp 127.0.0.1:3306: bind: address already in use
For the above error, that indicates that the mysqld
process is already running using that same port (3306). To confirm what ports are currently in use on your Mac, run the following command in your terminal:
sudo lsof -i -P | grep LISTEN
# Alternatively you can search for the specific port in your error, substituting 3306 the port you want.
sudo lsof -i -P | grep :3306
If you see a process that is using that port, that process should be stopped before you attempt to start or create any new environments with wp-local-docker.
If you installed mysqld
via Homebrew, you need to stop the process via Homebrew:
brew services stop mysql
Once you stop the service re-run the lsof
command above to verify the port is no longer in use.
This is likely to do with the change from the WP Snapshots system, to the new Snapshots WP-CLI command.
This update removed the need for a dedicated container for the snapshots system, and instead uses the phpfpm
container.
Because of this, we need to ensure that the phpfpm
container has access to the ~/.wpsnapshots
and ~/.aws
directories on your host machine.
To provide that access, please edit the docker-compose.yml
file in the environment you are updating, to add the following lines:
phpfpm:
image: '10up/wp-php-fpm-dev:7.4-ubuntu'
# ...
volumes:
# ...
- '~/.wpsnapshots:/home/www-data/.wpsnapshots:cached'
- '~/.aws:/home/www-data/.aws:cached,ro'
You'll then need to stop and start the environment for the changes to take effect.
If that doesn't resolve the issues, try updating your Docker images using 10updocker image update
, it could be that you have older images that don't yet have the Snapshots WP-CLI tool installed.
Migrating an old standalone WP Local Docker environment to a new WP Local Docker V2 environment is straightforward. First, create a new environment using the 10updocker create
command. Then, use the following command to perform the migration:
10updocker migrate <OLD_PATH> [NEW_ENV]
Here, <OLD_PATH>
should be the path to the root of your old WP Local Docker environment.
[NEW_ENV]
should specify the environment to import into. If you omit this, you will be prompted to select from available environments.
Here's an example:
10updocker migrate ~/sites/mysite
This command will migrate the environment located at ~/sites/mysite
to a new WP Local Docker V2 environment.
To upgrade your WP Local Docker V2 environment to V3, run the following command:
10updocker configure
When asked Do you want to reset your global services configuration? This will reset any customizations you have made.
, answer yes
.
This will update your configuration to the latest .wplocaldocker/global/docker-compose.yml
.
To upgrade your WP Local Docker V2 environment to V4, follow the steps below:
-
Update Docker images:
10updocker image update
-
Update WP Local Docker
npm install -g wp-local-docker@latest
-
Restart your terminal
-
Verify the version:
10updocker -v
This should return a
4.x.x
version. -
Update the
docker-compose.yml
files for your environments to grant access to the~/.aws
and~/.wpsnapshots
directoriesphpfpm: image: '10up/wp-php-fpm-dev:7.4-ubuntu' # ... volumes: # ... - '~/.wpsnapshots:/home/www-data/.wpsnapshots:cached' - '~/.aws:/home/www-data/.aws:cached,ro'
-
Restart your environment
10updocker restart <hostname>
-
Ensure Snapshots is functioning and has access to the data:
10updocker wp snapshots search test
This will complete the migration process from WP Local Docker V3 to V4.
Archived: This project is no longer maintained by 10up. We are no longer responding to Issues or Pull Requests unless they relate to security concerns. We encourage interested developers to fork this project and make it their own!