It has been a while since I have run a few Wordpress based sites. The database stores some of the content of the site. The file system stores media that is uploaded into the site. More significantly Wordpress is a Content Management System. The intention is that your site users can add content and media to the live site. When someone uses the WYSIWYG editor to add or edit the content you will find that the sites domain name leaks into the database. So if you move the Staging database into Live you would get links appearing on the Live that that point back to the Staging site.
I quick bit of research to see if things have improved since I last used it leads to this article on putting Wordpress into git. Please read the first article in that series that explains the challenges. You will need to understand a little of how Wordpress works to understand the recommendations I make below.
That article talks about turning off automatic updates so that you have to manually security path. I am pretty sure that I remember that updates can write things into the database. I would be very worried about turning off updates as there are a huge amount of attacks against Wordpress as it is so widely deployed. You really should avoid deploying many third party plugins as they might not get security patches in time. This isn't a theoretical problem I had quite a time dealing with Wordpress being used as a spam relay. Yet even if you follow that article you won't have solved the database migrations issue.
My recommendation is that you take a step back and try to figure out what problems you are trying to solve and how to adapt the tools and process:
- What is the developer developing? A custom Theme and/or Plugin? If so then this article covers that. Put the Theme/Plugin into its own repo.
- Who actually writes the site content or uploads media? The general public or members of staff? If it is staff then maybe they need minimal training in a Test environment and can happily edit Live after that.
Given that Wordpress does not let you aim for perfection due to the way that it is built, yet it is hugely successful, carefully pick which of the following you are aiming to optimise:
- A Specific Service Level Agreement
- Meantime to recovery
- Mean time between failures
- Reducing the commercial impact of errors
- Something else?
There are quite a few other specifics that may affect what set of compromises might work best for your situation.
Based on my experiences without actual knowledge of your specifics:
- Give up the idea of promoting changes through Dev, Staging and Live. I would simply have a Test site and a Live site. I would periodically refresh the Test site from the Live site. To do this I would dump out the entire Live database a run a
sed -i over it to replace every instance of "www.mysite.com" with "test.mysite.com".
- Give up on using Docker as the software distribution mechanism for the actual site. I would use Docker to supply the PHP+Apache runtime and mount a volume that contained the actual site php+content. This because the disk is a combination of the code and the content of the site so you need to be able to backup and restore it independently of changing the Docker image.
- Try "git checkout vX.Y" to update the live site in a persistent volume mounted into your generic PHP+Apache docker image. I would investigate the ideas in this series of articles.
- Automate the backup of the media content volume every night and keep as many backups as you can. This is why it needs to be a volume mounted into Docker.
- Automate the backup of the database every night and keep as many as you can.
- Automate the restore of the site as a script that restores the database to the last midnight backup then restores the last nightly snapshot of the media content folder.
- Avoid any party plugins that are not commercially supported. They likely won't work at the next major upgrade of Wordpress and will pin you onto a version that will become obsolete.
Then they workflow that I would go for would be the to add "experimental features" into the Test site before applying them to the Live site. This would be based on git checkouts in the best case. Yet I would also consider doing Wordpress security updates via the CLI. Those can update the database and the state on disk underneith Docker hence I do not recommend you try to mange the state of your site as a Docker image.
You then have to worry about the Test site drifting away form the Live site. So I would on a periodic base (at least monthly) overwrite the Test site with the Live site. This would involve:
- Backing up the Lite sites media content on the persistent volume and restoring it over the Test sites media content on its persistent volume.
- Backing up the Lite sites database, doing a
sed -i to rewrite any content links pointing at the Live to point at the Test site. Then restoring it over the Test database.
A key part of this approach is that you would be running your Live site like every other Wordpress site in the world. You don't do "brain surgery" on the Live site. You do frequently do "brain surgery" on the Test site. If the brain surgery goes wrong it's annoying and painful to fix but it is only the Test site that needs some new step to bring it into sync with Live. It is likely that this only happens when you move to a new Wordpress version. If you try a custom approach of moving change into a Live site they might break at a future Wordpress release and leave you with a multiple-day outage in Live.
I completely recognise that the approach outlined above isn't at all how "normal" software is developed. Yet it is the approach that I have scripted in the past. Even if you did the standard dev/test/live approach you do not guarantee 100% perfection and 0 bugs but you might have a longer mean time between failures. If you accept that perfection isn't possible then what you want is very fast rollback to reduce the impact of bugs. You do this by focusing on reducing the meantime to recovery to the speed of a restore script and the time taken to get permission/agreement to run it.
Being able to rehearse things in a Test environment should mostly avoid a total outage on the live site. Being able to do a fully automated restore can then bring you back to a good state at the loss of some recent edits to the site. That is normally completely acceptable compared to having an extended outage. Consider this scenario:
- Staff are continually editing content in production including uploading new media into the content folder on disk (e.g., uploading a PDF and linking to it within content where the link is in the database).
- You have run some Wordpress updates in Test a day ago and they seemed good. Today you run them at 9 am in the Live and something odd happens (maybe a timeout, whatever) and the site becomes corrupted.
- You have automated the rollback. You run the roll-back script which computes the last nightly full backup point then restores the database, then restores last night's media content folder backup over the live folder to revert any lost or corrupted files.
To my knowledge that is as good as you can get. Your meantime to recovery should be the speed of your database restore plus the time take to spot the problem and agree to do the restore. This is exactly why you shouldn't have to speak to editing Staff about whether or not they are happy with the roll-back as the site is broken so of course, they would agree to restore the site automatically, rather than have the site down for hours while a possible point fix is investigated and attempted. You can send out a prepared email telling Staff that there was an outage at 9 am such that the site has been restored to the previous nights backup and that they should double-check and repeat any work that they have undertaken in the past twenty-four hours and redo their work as necessary. IMHO that is as close to perfection as an opensource PHP content management system such as Wordpress allows.