Quickly spin up a headless Wordpress CMS on AWS using Docker
Headless CMS is very popular at the moment. But what is a headless CMS and why should I start using one?
A headless CMS is a backend that is decoupled from its frontends. The backend is where the content is created and published. Whereas the frontends are where the content is displayed (web, mobile apps, set-top box, Alexa, etc…).
For example, a traditional CMS is a single website. The same website is used to add the content as it is to display the content. The backend and frontend are coupled.
A headless CMS is only used to created and publish content. That content is then available through an API. The website or mobile apps, for displaying the content, are separate.
But why is decoupled better? Here are some of the reasons:
- Faster and more flexible content delivery than traditional CMS
- Resiliency in the face of changes on the user interface side (future-proof)
- Rapid design iterations
- Enhanced security
- Fewer publisher and developer dependencies
- Simpler deployment
*** Thanks for the list Brightspot
Now that we all emphatically agree that headless CMS is the way to go. Let’s take a look at these awesome CloudFormation templates I created to help you spin up and manage your headless (Wordpress) CMS.
To be clear, this is a Wordpress installation running on AWS using Infrastructure as Code and Docker.
Wait… Why use Wordpress and not one of these cool new headless CMS services like Contently or Cosmic JS? Well, these services are really great but they cost a lot of money, and I usually like to run everything myself, if I can help it. And… Wordpress is really good at managing content.
But how can Wordpress be a headless CMS? Easy, it has an API.
The trick is making Wordpress stateless so that it can autoscale, and run on AWS, with zero-downtime deployments.
Ok, headless CMS is cool, Wordpress is pretty cool, let's continue.
Our Wordpress instance is running as an Elastic Container Service using Docker.
First we have the VPC, then an ECS cluster, then an EC2 instance, and finally an ECS service with tasks. Our Wordpress service is exposed to the world via an Elastic Load Balancer. We’re using RDS as our MySQL database.
Our Wordpress service is stateless, which means we can’t rely on the file system to store content, like Wordpress Media or Plugins. Every time an instance of our Wordpress service is spawned it will only have the files that are baked into our Docker image.
Let’s take a look at how we handle Wordpress Media first.
We use a plugin called WP Offload Media. This plugin allows us to store the Media in S3 and use CloudFront as the CDN. Take a look at the diagram below. We also use the same CDN to cache the Wordpress API…
Now how do we handle the Plugins? (We can ignore Templates because this is headless 😃)
Remember when I talked about baking things into our Docker image? That’s it… We have to include the Plugins in our Docker image. Let’s take a look at that Dockerfile and go through it.
As you can see our Dockerfile is really simple. It extends the latest Wordpress image and then installs 3 Plugins. It downloads, unzips, and copies each plugin to the
wordpress/wp-content/ directory. When you launch your Wordpress site for the first time you’ll have to activate these plugins. The activation status is stored in MySQL so you won’t have to do it every time your ECS tasks recycle.
Alright, let’s get this architecture installed. First a few prerequisites.
Install the following prerequisites:
Now let’s install each stack one at a time.
This creates the Amazon Virtual Private Cloud that our ECS cluster and RDS database will run in.
Amazon Virtual Private Cloud (Amazon VPC) lets you provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define.
This creates an Elastic Container Service that our EC2’s will run in.
Amazon Elastic Container Service (Amazon ECS) is a highly scalable, high-performance container orchestration service that supports Docker containers and allows you to easily run and scale containerized applications on AWS.
This creates a Relational Database Service database cluster that our Wordpress application will use.
Amazon Relational Database Service (Amazon RDS) makes it easy to set up, operate, and scale a relational database in the cloud.
export DatabaseUsername="???"; export DatabasePassword="???"; cim stack-up
This creates an Elastic Container Registry that will hold the docker images of our wordpress service.
Amazon Elastic Container Registry (ECR) is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images.
Before we can launch this CloudFormation stack. We need to push our Wordpress image to ECR.
aws ecr get-login --registry-ids <account-id>
- copy/past output to perform docker login, also append
/headless-wpto the repository url.
docker build -t headless-wp:<version> .
docker tag headless-wp:<version> <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp:latest
docker tag headless-wp:<version> <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp:<version>
docker push <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp
Make sure the
Version parameter, in _cim.yml, matches the
version tag from above. The ECS Task Definition will pull the image from ECR.
Version is set you can use
cim stack-up to update the stack with the new version.
Congratulations, your new Wordpress site is now available.
First run through the Wordpress setup wizard.
Next enable some of the plugins we added.
Add a few blog posts and pages.
Then check out the API. Ex:
Congratulations on getting your Headless Wordpress installed. If you got stuck anywhere along the way please don’t hesitate to reach out to me for help.
One thing I want to explain is the Wordpress environment variables because they really tie everything together. They tell our Wordpress installation about the RDS database, the Media S3 bucket, and CloudFront CDN URL. Let’s take a look. These can be found in the Wordpress stack’s AWS::ECS::TaskDefinition.
WORDPRESS_DB_* variables are straight from the RDS stack. CloudFormation allows you to Export Output variables which can be imported in other stacks.
WORDPRESS_CONFIG_EXTRA variable is where we configure the WP Offload Media plugin. First we tell it to use our Task Role, AWS::IAM::Role, via the
AS3CF_AWS_USE_EC2_IAM_ROLE var. Then we the
AS3CF_SETTINGS var to setup the plugin.
Thanks for reading. I hope you enjoyed it!