Deploying WordPress on ECS with AWS Copilot

When I decided to start a blog I naturally went through a lot of thoughts regarding how to solve my desired outcome. My main goal is to share knowledge and things I’ve learned which might be useful for others, but also to learn something new for myself during the process.

I quickly decided that I wanted to use the opportunity to find the optimal way for my use-case to self-host my site. Since cloud technology and Amazon Web Services is my area of expertise, this became a natural place to start.

But before we begin choosing technical solutions, let’s first define our objectives, what we want to achieve.

  • My “customers” will have a great user experience
  • The content is relevant for my target audience
  • The supporting infrastructure is simple, but scalable, and of low effort to maintain
  • The solution is cost effective, but also with sustainability in mind
  • The solution is Well-Architected
  • I learn something new

There are many ways to deploy WordPress in AWS (this will be a future blog post of it’s own!), with pre-packaged Amazon Machine Images (AMIs) and containers. But, since friends don’t let friends run EC2 instances anymore, I went for a container based approach.

The next step was then to consider Infrastructure-as-Code options for automation. I have many years of experience with AWS Cloudformation and HashiCorp Terraform, and there are many public Terraform modules out there, but a service which has caught my attention for the last year or so is AWS Copilot, which is described as:

“AWS Copilot is a command line interface (CLI) that you can use to quickly launch and manage containerized applications on AWS. It simplifies running applications on Amazon Elastic Container Service (ECS), AWS Fargate, and AWS App Runner.”

AWS Copilot
Image courtesy of AWS: https://aws.amazon.com/containers/copilot/

This was a great use-case to evaluate AWS Copilot and the Load Balancer Web Service architecture model. The AWS Copilot CLI Documentation has an area dedicated to community guides and resources, where I found a blueprint for launching WordPress.

The end result is as follows:

  • AWS Application Load Balancer with TLS termination
  • Amazon Elastic Container Service (ECS) Service with Auto Scaling
  • Amazon Aurora Serverless MySQL database cluster (V1 can scale in to 0)
  • Amazon Elastic File System mounted for persistent storage

To make the site even more snappy I installed the WordPress plugin Staatic which publishes the site to flat HTML files in an Simple Storage Service (S3) bucket. I put Amazon Cloudfront as CDN on top and serve it all through a dedicated domain with a certificate provisioned with Amazon Certificate Manager (ACM). HTTP headers such as Cache-Control: max-age is set on relevant objects in S3 in addition to Cloudfront Functions as fallback.

When I set the ECS service Desired and Auto Scaling Minimum counts to 0, the container tasks will shut down, and after a short while the Aurora Serverless database cluster will pause. When I want to write a new post, I just change the ECS Service configuration for Desired Tasks back to 1 and the whole solution is up and running again. Cost efficient and sustainable!

To avoid situations where I forget to shut down the container instance I made a very simple Lambda function which I named “ecs-service-shutdown”, which is triggered by an EventBridge rule every night at 02:00.

import boto3

ecs = boto3.client('ecs')

cluster = 'wordpress-prod-Cluster-Kz26rMlfqa6r'
service = 'wordpress-prod-blog-Service-zI8pVnNa0YzE'

def lambda_handler(event, context):
    response = ecs.update_service(
        cluster=cluster,
        service=service,
        desiredCount=0
    )
    print(response)
    return {
        'statusCode': 200
    }

To get going with AWS Copilot check out https://aws.github.io/copilot-cli/ .

Image courtesy of AWS: https://github.com/aws/copilot-cli/

Posted

in

by

Tags: