Running WordPress locally with Docker on Windows
So basically there are at least a few options to run WP locally – in the old days it was mostly XAMPP and it was a royal pain in the ass.
The times have changed, and now we actually have some decent options to set up local environments in a few minutes – the most popular would be Laragon, LocalWP and Docker (sometimes with an additional layer of DDEV).
Laragon is really neat – with quickapp it’s just a few clicks for a fully functional WordPress installation, and it even has a local mail handler!
It’s lightweight, quite fast, and file management is rather more “direct” if you will.
With LocalWP I haven’t really got much experience; for some reason I couldn’t run it optimally on my system, and all the pointers to fix that issue were rather vague at best. I like to tinker around, but I value my time, and at some point I just gave up on trying. From what I’ve got it’s kinda „local for dummies” and that’s perfectly ok if you would prefer it that way. It has some cool features like Live Links for online reviewing, hot swaps for environments, Mailpit for local e-mail handling, WP-CLI and Instant Reload, which in every other instance can be swapped with plugins like Live Auto Refresh.
The last option will be Docker, which is the actual protagonist of this blog post.
In my case it was the winner, simply because it ran the local fastest among all of the other options. It took a while to get used to containerized handling of my WP, but once you get the hang of things, it’s quite nice – and besides, it’s industry standard for some reason too.
Ok, so without further ado.
What you will need?
- a new folder, where you will manage Docker containers (installations);
- two files to work as a template;
- access to PowerShell, CMD or any other environment compatible with Docker (PowerShell and CMD should be available by default).
Instructions
Create a new folder that will work as a base for your container(s).
Here you will handle all the “manual” editing, setting configurations for environments, and doing all the other things, like checking debug.log, when needed.
It doesn’t matter how you’ll name it.
Setup configuration files for your container(s)
Inside the folder created for all your containers add a new one, specifically meant for the new container you are making.
This is the hardest part (at first), because you need to keep in mind a few things.
.env file
Create a new file named .env and fill it with:
# Database Configuration
DB_ROOT_PASSWORD=password
DB_NAME=wordpress
DB_USER=root
DB_PASSWORD=password
# WordPress Configuration
WP_PORT=8070
All the DV_ variables are, of course, related to your database, and with those, you can access it via PHPMyAdmin, Adminer, or any other DB manager.
WP_PORT is the actual port that will work as a gateway for your local address—i.e., http://localhost:8070/ in this case.
docker-compose.yml file
This one is kind of „bulky” and contains all the required info for Docker to create the actual container.
services:
db:
image: mariadb:latest
container_name: wordpress_db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
networks:
- wordpress_network
wordpress:
depends_on:
- db
image: wordpress:php8.4
container_name: wp_main
restart: unless-stopped
ports:
- "${WP_PORT}:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: ${DB_NAME}
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_CONFIG_EXTRA: |
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
define('SCRIPT_DEBUG', false);
volumes:
- wp_data:/var/www/html
- ./my_theme:/var/www/html/wp-content/themes/my_theme
# - ./php/custom.ini:/usr/local/etc/php/conf.d/custom.ini
# - ./adminer-5.4.2-mysql.php:/var/www/html/adminer-5.4.2-mysql.php
# - ./wp-content/debug.log:/var/www/html/wp-content/debug.log
networks:
- wordpress_network
volumes:
db_data:
wp_data:
networks:
wordpress_network:
driver: bridge
Summary of less “descriptive” values
db: image: mariadb:latest– is the latest image for an instance of MariaDB; usually you want to run your WP installation on it instead of MySQL (it scales better and provides better query speed in most cases);wordpress: image: wordpress:php8.4– there are plenty of images to choose from, but for now we’re using the one with the latest stable PHP version;wordpress: ports: - "${WP_PORT}:80"– has to stay at port 80wordpress: environment: WORDPRESS_CONFIG_EXTRA: |– additional guidelines for wp-config.php; since we’re not going to manage it directly, in this particular case it’s basically for debug, so anytime you need to switch it on, just change variables and rundocker compose up -d;wordpress: volumes:– is basically for syncing with our local folder(s); if you need to sync a particular folder, just add it here in the format of local-folder:docker-folder;wordpress: volumes: - wp_data:/var/www/html– syncing of WP installation files;wordpress: volumes: - ./my_theme:/var/www/html/wp-content/themes/my_theme– your theme folder; just keep in mind that Docker will load everything from it, so you need to provide a complete set of files required for it;wordpress: volumes: - ./php/custom.ini:/usr/local/etc/php/conf.d/custom.ini– this is the file where you can set custom variables for the PHP environment, like upload_max_filesize, max_execution_time, etc. – you don’t „require” it by default, but since the image is using the bare minimum to run the installation and some plugins will just plainly break with the image defaults, I would say that you should remove that # and keep it just in case;wordpress: volumes: - ./adminer-5.4.2-mysql.php:/var/www/html/adminer-5.4.2-mysql.php– database management; Adminer is simply faster and easier to set up, so my advice is to keep that line commented till you need it; if you still want to use PHPMyAdmin instead, then check that guide out;wordpress: volumes: - ./wp-content/debug.log:/var/www/html/wp-content/debug.log– obviously is for syncing debug.log file; Docker won’t create it locally by default, so you need to point it in case you’ll debug.
# before the actual line means it’s commented out and won’t be considered during the build.
Run Powershell
It’s rather simple: open the folder for your container (one with the configuration files), click on the address bar (for example, This computer > D: > docker_containers > wp_main), type “Powershell” and tap enter. It should open a PowerShell instance with the folder you’re currently in.
Now enter the magic command:
docker compose up -d
and tap enter.
It will take a minute or two to build, and after that, simply open Docker, wait for all the inits, and access your container via http://localhost:8070/ (or any other port you have chosen) in your browser.
Anytime you change variables, add volumes to sync, enable debug, or anything else, just run PowerShell and hit it with the same command:
docker compose up -d
It will take a few seconds at best.
That’s it.
It’s the setup for most basic needs in local development.