I don’t work with WordPress often anymore, but when I do I don’t particularly enjoy it. I certainly used to enjoy it but since working with more modern development practices, WordPress plugin or theme development feels like a hassle. It feels cumbersome and the development experience (DX) is clunky, especially if I have to wait for a Virtual Machine (VM) to start, copy over 250 MBs worth of plugins and themes, export a database, run a search & replace on that database, import that database, and then finally start development on the new feature.
It just seems like things could be better but then again, maybe I’ve been spoiled by working with SvelteKit apps that are deployed at edge with a simple git push origin main
command run from my terminal. 🤷
In any case, I’ve still got clients that use WordPress so I’m stuck working with it. To reduce my pain and frustrations, I’ve revisited how I was developing WordPress locally with Docker. I’ve made some improvements to my docker-compose.yml
by adding a PHPMyAdmin container as well as a WP-CLI container.
docker-compose.yml
services:
db:
container_name: ${NAME}-db
image: mariadb:10.6.4-focal
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: on-failure
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
expose:
- 3306
- 33060
wordpress:
container_name: ${NAME}-wp
depends_on:
- db
image: wordpress:latest
ports:
- 8000:80
restart: on-failure
volumes:
- .:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=${MYSQL_USER}
- WORDPRESS_DB_PASSWORD=${MYSQL_PASSWORD}
- WORDPRESS_DB_NAME=${MYSQL_DATABASE}
phpmyadmin:
container_name: ${NAME}-phpmyadmin
depends_on:
- db
restart: on-failure
ports:
- 8080:80
image: phpmyadmin/phpmyadmin
volumes:
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
environment:
PMA_HOST: db:3306
PMA_USER: root
PMA_PORT: 3306
PMA_PASSWORD: ${MYSQL_PASSWORD}
wpcli:
container_name: ${NAME}-wpcli
depends_on:
- wordpress
image: wordpress:cli
restart: on-failure
command: tail -f /dev/null
volumes:
- .:/var/www/html
environment:
- WORDPRESS_DB_HOST=db:3306
- WORDPRESS_DB_USER=${MYSQL_USER}
- WORDPRESS_DB_PASSWORD=${MYSQL_PASSWORD}
- WORDPRESS_DB_NAME=${MYSQL_DATABASE}
volumes:
db_data:
This new version makes use of a .env
file which allows for naming the containers and setting passwords from one single file. I’ve created a GitHub repository of this starter template so that I can quickly get up and running with a new WP site locally. A lot of these changes were inspired by Marinus Klasen and taken from his post titled “Adding and using WP-CLI in a docker compose setup.” That post from his website can be found here.
This setup doesn’t come without it’s pain points though. There is still an issue when it comes to permissions in the wp-content/
directory so if you’re using it, expect to be modifying ownership or permissions regularly. Honestly, it’s probably easier to use a tool like Local by Flywheel but I’m a glutton for punishment 😉.
Developing Custom Plugins
I began setting up this new workflow because a SUPER AWESOME CLIENT of mine and I agreed that the 3rd party script he was using was less than ideal. The script was simple enough to include on any website. But it essentially worked by creating a big blue button in the bottom right-side of the page and when clicked, users would be able view the Workout of the Day (WOD) for the gym.
The problem with this approach is that it looked really out of place on the website. And since the content was controlled by a the 3rd party provider, instructions had to be added to the page so users would know to click the button to find the WOD 🤮. Instead of including this script and button, I thought it would be nice to simply grab the data myself and display it on the page 👍.
But to do that, I would need a custom WordPress plugin. I also needed to ensure it would work with the existing theme and look better than what we already had. All of this meant I would need to download the production site and get it up and running locally, hence all of the changes to my Docker + WordPress setup.
I’m not going to go into details about developing custom WordPress plugins because there is already tons of articles and documentation explaining this. Instead, I’m just going to link to the GitHub repository here. This way, if you or someone you know finds themselves wanting to display the Workout of the Day from SugarWOD on their gym’s WordPress website, they absolutely can. Instructions are included in the repository’s readme file.