Docker Compose Development Environment for WordPress

2/12/2023, 6:13:36 PM

Thomas Prosser

Now and then, I get asked how I do small websites (and if I’d also do a very small one for free, but that’s beside the point).

WordPress is still my goto

When I want to get something up quickly, WordPress is still my go-to content management system. It’s easy to understand for the end-user, it can be deployed on basically every hosting-provider out there and it comes with batteries included. Nice templates that can work out-of-the-box, a really simple data model and a database for persistence. It helps you versioning your content and its ecosystem is so vast that there is definitely a theme or plugin out there you can use directly or tweak it for your needs. On top of that, most providers enable you to provision a site with the click of a mouse button.

As a consequence, when researching about how to best develop for WordPress, I realized that there are people who focus on web design and mostly worry about the templates folder of a WordPress installation, if at all, and then, there are poeple who post videos about how to develop a plugin. Some of the content I encountered in the wild was about combining plugins to give a good UX and all have their merits. But when it comes to professional work, where you actually have to develop something that is specific to a site or implement a theme you got from a designer, you will sooner or later have to start programming. PHP, HTML, CSS, JavaScript…


Most tutorials would then fire up an editor such as VSCode and use some direct sFTP or SCP connection to their live server in order to see their changes in action. Not only is that open-heart surgery on your production site, it can also take it down for hours on end until you just fixed that little bug. Some go a little further and use tools like Wamp or Mamp (its Mac equivalent). That means running a DB and a web server on your system. You could then use a virtual machine, which also drains resources and if you’re like me, you will forget which machine has the right configuration for the task. And what’s more, it also means you configure wordpress yourself first before you can start figuring out how to get your files to the right machine or into the right directory. There cas to be a simpler way. So I googled around and came up with a solution which:

  • Allows me to keep my files in a project directory
  • By this, I mean really only the plugin and/or theme directory I develop
  • Make changes visible immediately in the virtual environment (hot-refresh)
  • Does not drain my system too much
  • Is much more lightweight to put under version control
  • Lends itself to a seamless integration into a CI/CD system if you want that

Docker Compose to the rescue

In our DevOps world, it is easy for a developer to configure his own environment without worrying about network connections, environments and connection strings and with just a few lines of code. Docker makes it very easy to bring up an environment which takes in the files in your project directory and serve them up in a concerted collection of necessary containers. Moreover, there are existing Docker images for you to use that you just have to configure a little to get them to work. Now, I could run different Docker files but as WordPress is usually served transparently for the developer, I chose to instead use Docker Compose for bringing up MySQL, phpMyAdmin and WordPress in a standard installation, linking in my project folder, .gitignoring and .dockerignoring the files I don’t need in prod and start coding. So without futher ado, here’s my docker-compose.yml:

Let me quickly walk you through it:

  • I use three services, db, phpmyadmin and wordpress, respectively
  • As you can see, all three images are official images from the respecive tool developers, so no need to brew my own (I’d rather brew beer instead).
  • The relevant environment variables documentation can be found on dockerhub, note that for the wordpress image, I set the DB port to db:3306. I exposed the DB on its standard port, which necessitated a mapping in the service. The db – prefix is necessary, because that is the DB’s network address within Docker Compose (note that I did not bother to configure a network since I use the normal bridge driver which is implied).
  • I mapped the data directory of the DB to a volume on my system. I could have left the portion before the column out (the ./data/mysql – part) but I wanted to control where the DB stores its data in case I need it. I need the volume hovever, otherwise all content is lost if I stop the containers.
  • phpMyadmin is not strictly necessary, as you could use any MySQL admin tool on your system, but hey! Why not… It’s free, it’s got all the functionality I need and it’s gone as soon as I remove the image from my system. You need an admin tool if you write stuff to the DB from your plugin or so…
  • The most important part are the four volume mappings for the actual wordpress image (the last four rows). I map two directories (./cz-gallery-plugin and ./cz-theme) to the directories where they would sit in a prod installation. I also map ./sparkling theme directory to the image because I develop a child theme from it, and the uploads are just there so I can see what happens to the media uploads (it is a site heavily relying on pictures).

That is basically it. Just fire up docker-compose up -d and point your browser to http://localhost. Start coding and your changes will be a page reload away (maybe not so hot-refresh after all, but maybe someone forks this gist and improves on it…)

Hope that helps someone out there. Feel free to comment.

Cheers and happy coding!