I have recently been building a webapp as a side project. It involves a WordPress website, with a WooCommerce plugin, and a NodeJS backend.
With my devops background, it seemed obvious to automate the installation of this application – so creating a volume, a database and WordPress containers from nothing with Docker and a docker-compose file.
However, what wasn’t so obvious was how to configure WordPress. WordPress has traditionally been an application that you configure via its user interface, but this does not lend itself to automation. I could rerun my build process, but I’d need to click a few buttons before I could actually test my latest change.
Given this was a side project, and I wasn’t under pressure from anyone, I took the time to automate the difficult bits. Getting WordPress configured and plugins installed using the WordPress CLI. Faking the WooCommerce setup wizard so that I can upload products via the WooCommerce NodeJS client and API. Pulling key data from a Google spreadsheet.
I can now redeploy the entire application, database, volumes, plugins, products, product images, etc, in under a minute on my laptop. I also have a “watch” tool that pushes small changes directly into running containers.
This gives me a profound development environment. Fast iterations on small changes via the watch tool, and slower (but far from lethargic) iterations for installation changes.
And on top of this, when everything installs from scratch, every single line of code is exercised, meaning my installation code has been exercised many hundreds of times – I know how reliable it is, and where its failure points are.
One of the key points that I learned on a previous project, and exercised here, was about ‘out of order’ startup. Let’s say we start MySQL, WordPress, our plugin installer and our WooCommerce product importer all at the same time. The plugin installer will fail if WordPress isn’t available. The product importer will fail if the WooCommerce plugin has not yet been configured. The solution is to make each component wait for its dependencies. A simple ‘nc’ command (while ! nc -z -w1 db 3306; do sleep 1; done) will make the Docker entrypoint script wait for MySQL. A similar one (while ! nc -z -w1 wordpress 80; do sleep 1; done) will make it wait for WordPress to be available. Likewise, tests for WooCommerce may be in the NodeJS code, With this code in place, I can reliably start everything up and know it will just work.
The knack here really is to automate 100% of the process. If you leave one click needed before you can test your application, that click is one you need to do every time. Over time, that adds up. The saving in time, and improvement in efficiency by automating 100% of product setup are astounding to see – even to someone who spends a lot of their time automating other people’s products!
Now if I take myself back, and think of an imaginary manager. Someone telling me they need this app running as fast as possible – they might consider this effort of automation to be overkill. And, in terms of delivering initial functionality fast, it clearly was. However, now that it is established, the benefit is clear enough that any manager would be convinced.