web dev & more!

WordPress + Docker v2

Published: January 18, 2024

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.

Want to become a super aweome client and get your own custom wordpress plugins, website, or web app? Click here and fill out the form!

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.