Running wordpress on ECS

Recently I need to setup a POC website for one of my project to validate the idea, and I decided to go with wordpress since it’s a very power tool and easy to setup. Since all my app are on ECS already so I decide to do wordpress on ECS as well.

WordPress provides a docker image already. And to make use of the docker image there are two things stateful needed to be handle:

  1. databaseĀ data
  2. wp-content directory

Database

For database, I already have a RDS instance for it. It’s also easy to config in wordpress image.

WP-CONTENT

The wp-content directory is where wordpress stores all the uploaded files, installed plugins and theme files. It must be mounted to docker so changes are persistent outside ECS.

EFS is used to do this: I created a EFS volume, and mount it for each of my ECS instances (set it up in user data so it’ll mount automatically for new instances), then in the ECS task definition mount the efs drive to docker volumeĀ /var/www/html/wp-content.

For a comparison between EFS/EBS/S3, check EFS FAQ. Basically EFS makes a good balance between performance and availability, it fits my usage for concurrent accessibility.

Detailed Steps

Assuming a ECS cluster already exists.

  1. Create an EFS volume, make sure it’s in the same availability zones with ECS cluster.
  2. I used spot instance for my ECS cluster (highly recommended for cost saving), so I just created a new spot fleet request and in user data we just need to join ECS cluster and attach the efs drive. A sample user data is showed below.
  3. Update ECS tasks and services to use the mount. I also have a sample script that register task and update service below.

User Data


#!/bin/bash
# join ECS cluster
echo ECS_CLUSTER=cluster-name >> /etc/ecs/ecs.config

# mount efs
mkdir /efs-drive
yum install -y amazon-efs-utils
sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 efs-id.efs.us-east-1.amazonaws.com:/ /efs
mount | grep efs
sudo cp /etc/fstab /etc/fstab.bak
echo 'efs-id.efs.us-east-1.amazonaws.com:/ /efs nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0' | sudo tee -a /etc/fstab
sudo mount -a

Update ECS Task


import boto3

client = boto3.client('ecs')
image = 'wordpress'
app_name = 'my-website'


def main():
    # register new version of task
    resp = client.register_task_definition(
        family=app_name,
        containerDefinitions=[
            {
                'name': app_name,
                'image': image,
                'cpu': 256,
                'memory': 256,
                'portMappings': [
                    {
                        'containerPort': 80
                    },
                ],
                'essential': True,
                'mountPoints': [
                    {
                        'containerPath': '/var/www/html/wp-content',
                        'sourceVolume': 'efs-wp-content'
                    }
                ],
                'environment': [
                    {
                        'name': 'WORDPRESS_DB_HOST',
                        'value': 'db-host'
                    },
                    {
                        'name': 'WORDPRESS_DB_NAME',
                        'value': 'db-name'
                    },
                    {
                        'name': 'WORDPRESS_DB_USER',
                        'value': 'db-user'
                    },
                    {
                        'name': 'WORDPRESS_DB_PASSWORD',
                        'value': 'db-pass'
                    }
                ],
                'healthCheck': {
                    'command': [
                        'curl',
                        'http://localhost:80'
                    ],
                    'interval': 60,
                    'timeout': 20,
                    'retries': 1,
                    'startPeriod': 120
                }
            },
        ],
        volumes=[
            {
                'host': {
                    'sourcePath': '/efs-drive/wp-content'
                },
                'name': 'efs-wp-content'
            }
        ],
        requiresCompatibilities=['EC2']
    )

    # update ecs service to pick new task
    family = resp['taskDefinition']['family']
    revision = resp['taskDefinition']['revision']
    new_task_arn = family + ':' + str(revision)
    resp = client.update_service(
        cluster='ECS',
        service=app_name,
        desiredCount=2,
        taskDefinition=new_task_arn,
        healthCheckGracePeriodSeconds=120
    )


if __name__ == '__main__':
    main()

Advertisements
Running wordpress on ECS