As an independent Cloud Consultant for multiple agencies,, I deal with some truly massive scalability challenges.
So when I decided to setup my own blog, using WordPress, it was natural for me to build something that can be scaled to sustain hundreds of thousands of users per day. But of course I didn’t want to spend a ton of money doing it, preferably I would like to start for free.
That is when I came up with a Dockerized clustered Wordpress architecture that can be scaled up and down quickly and conveniently without changing any code or incurring any down time with almost zero startup cost. Many thanks to AWS free tiers.
Following image describes the general architecture of the solution.
The very first step is to create a docker image for my site that uses the base Wordpress docker image and replaced my local wp-content directory, that contains my favorite plugins and themes. This is important because without a dockerized solution it will be very difficult and time consuming to run the exact same Wordpress image on every instance in the cluster. Here is what my docker file looks like, thanks to the official Wordpress base image.
FROM wordpress:5.1.1 RUN rm -rf /var/www/html/wp-content COPY ./wp-content /var/www/html/wp-content
All I need to do now is install my favorite plugins and themes locally, remove the ones I don’t like, build and push my image to docker hub to be deployed anywhere I like.
I used docker compose for my local development environment that adds a local instance of MySQL. This way, I can build and test my site locally before deploying it to the production instance in AWS. Here is what my docker compose file looks like:
version: '3' services: wp: image: naveed125/effective-programmer:latest restart: always ports: - "8080:80" volumes: - ./wp-content:/var/www/html/wp-content links: - db environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_PASSWORD: p4ssw0rd! WORDPRESS_CONFIG_EXTRA: define('AS3CF_SETTINGS', '...'); db: image: mysql:5.7 restart: always environment: MYSQL_ROOT_PASSWORD: dbp4ss! volumes: - ./data/mysql:/var/lib/mysql
Production Server (Clustered)
Once I am satisfied with my local install, the next step is to launch it in the production environment. I started with a single free EC2 instance in AWS that will host my container. This could be very easily scaled up, all that's needed is to launch more EC2 instances and deploy my containers on them.
At the moment I am doing it manually but in the near future I plan to use ECS with auto scaling for convenient control of my cluster.
In a clustered environment all WordPress instances need to connect to the same database, so a docker-compose based solution will not work. I started with a free MySQL instance in RDS that can be scaled to use a larger instance depending on my site’s traffic.
Centralized Uploaded Files
I needed a centralized solution for my uploaded files, otherwise uploaded media and files will only reside on the server instance that was used for upload and most pages will appear broken depending on which server handles the page request.
To solve this, I used the free WP Offload Media Light plugin to handle uploads to S3 and used the settings to remove uploaded file from the container. This plugin automatically replaces the file URLs with S3 URLs and has excellent documentation on how to safely set it up. It also supports CDN so in the future I plan to put CloudFront in front my S3 bucket for maximum download efficiency.
I registered my domain with my favorite Domain Hosting Provider Hostinger* and pointed it to an Elastic Load Balancer in EC2 that in turns points to my WordPress instance(s).
*Note that domain registration wasn’t free.
One of the amazing benefits of AWS is the free SSL certificate you can obtain through the Certificate Manager for your site with simply doing a domain verification. You don’t even have to host the domain with AWS.
Upgrades and Updates
Upgrades and updates to themes, plugins and WordPress itself are easy to handle. First install and test the update locally, then build and push docker image and update the containers on the cluster.
Security and Monitoring
Security is a big issue for WordPress sites, within seconds of launch i was hit by a massive comment spam. At the same time I felt the need to have some decent solution to track my site’s statistics. Incidentally a essential plugin, Jetpack by the WordPress team solves both of these in a fantastic way. I ended up disabling comments for the time being to avoid paying for the paid akismet solution. Yeah I was really going for free here :)
There are still a couple of things I would like to do to improve my clusters’ health and make it load the pages quickly and efficiently. As I mention above setting up a CDN, adding caching, and using ECS instead of manual deployment will go a long way and I plan to add these over time.
Would love to hear what you think about my setup or if you have any suggestions for improvement or questions. And don’t forget to checkout my other writings here.