Run WordPress on Amazon ECS and RDS with mu
We can use mu to:
- customize the official WordPress Docker image,
- storing a copy in Amazon's ECR Docker registry,
- running it in Amazon's EC2 Container Service,
- fronted by an Application Load Balancer,
- backed by an RDS Aurora database,
- deployed with CodeBuild and CodePipeline,
Mu does it all for you through AWS CloudFormation using a pair of simple YAML files.
GitHub stores your infrastructural code.
mu acts as your front-end to AWS by generating and applying CloudFront templates, orchestrated by CodePipeline.
The official WordPress Docker container is deployed to Amazon ECS, and your custom copy is stored in Amazon ECR.
An ECS cluster is run for each environment we define, "test" and "prod".
An AWS ALB sits in front of each cluster.
Your WordPress database will be provided by an Amazon RDS cluster, one for each environment. Each runs Aurora, Amazon's highly optimized clone of MySQL.
AWS CodePipeline orchestrates all the other services in AWS. It's used to give you a continuous delivery pipeline:
- It watches your GitHub repo for changes and automatically applies them shortly after you push.
- AWS CodeBuild uses
buildspec.ymlto run any custom steps you add there.
- AWS CodeBuild generates your own Docker image by combining the results of the last step with the official WordPress image and storing it in Amazon ECR.
- Your container is deployed to your "test" environment.
- You manually inspect your container and approve or reject it.
- If you approve it, your container is deployed to your "prod" environment.
git clone _your_fork_of_mu-wordpress_ cd mu-wordpress
(Why do all that instead of just cloning? You don't technically need to fork the Stelligent mu-wordpress repo unless you want to follow its changes, but it's a convenient way to get a copy in your GitHub account.)
CodePipeline is going to watch your repo for changes, which will give you power-user convenience: just push your code to trigger updates in your WordPress deployment. Infrastructure as Code, amiright?
mu.yml and change
pipeline.source.repo to point to your
own GitHub account instead of "stelligent":
pipeline: source: provider: GitHub repo: _your_github_username_/mu-wordpress
Set your AWS region if you want to use something other than the default,
Let's create a keypair you can use to debug any issues that might come up on your containerized EC2 instances:
ssh-keygen -C mu-wordpress -f ~/.ssh/mu-wordpress aws ec2 import-key-pair --key-name mu-wordpress \ --public-key-material file:///$HOME/.ssh/mu-wordpress.pub
The key named "mu-wordpress" is referenced in
mu.yml. If you use
a different name, or don't want to define a key at all, be sure to
keyName definition there.
Commit your changes and push them back up to your GitHub account:
git add mu.yml git commit -m'first config' && git push
Spin it up
Start up your pipeline, which will deploy to 2 environments, "test" and "prod":
mu pipeline up
Mu will ask you for a GitHub token. CodePipeline uses it to watch your repo for changes so that it can automatically deploy them. Create a new token in your own GitHub account and grant it the "admin:repo_hook" and "admin" permissions. Save it somewhere, like a nice password manager. Enter it when mu asks for it. (But don't give it to anything else! ;^)
Watch your pipeline get deployed:
mu pipeline logs -f
When that's done, you can verify that you have 2 environments, "test" and "prod":
mu env list
You'll see a table like this:
+-------------+-----------------------+---------------------+---------------------+------------+ | ENVIRONMENT | STACK | STATUS | LAST UPDATE | MU VERSION | +-------------+-----------------------+---------------------+---------------------+------------+ | test | mu-cluster-test | CREATE_COMPLETE | 2017-05-23 14:48:04 | 0.1.13 | | prod | mu-cluster-prod | CREATE_COMPLETE | 2017-05-23 16:23:28 | 0.1.13 | +-------------+-----------------------+---------------------+---------------------+------------+
You can view the details on any of the environments:
mu env show test
If you want to watch the "test" environment's services get deployed, or view logs from the "test" environment, try these:
mu service logs -f test mu env logs -f test
When your test environment is initialized, you can load the WordPress admin installer and get your site started. Find the base URL with:
mu env show test
You'll see a block at the top that includes "Base URL":
Environment: test Cluster Stack: mu-cluster-test (UPDATE_IN_PROGRESS) VPC Stack: mu-vpc-test (UPDATE_COMPLETE) Bastion Host: 126.96.36.199 Base URL: http://mu-cl-some-long-uuid.us-west-2.elb.amazonaws.com
Append "/wp-admin" to that and load the URL in your browser:
Follow the instructions there to set up a WordPress admin user, initialize the database, etc.
Update your content
Everything in your repo's
html directory will be installed in your
containers. Add files there and they'll end up in
right alongside WordPress. Want to install persistent plugins?
Put them in
html/wp-content/plugins. Want to install a theme?
Add it to
This is a really simple proof-of-concept for deploying and managing a WordPress installation through code. Making it robust is more complex, and not within the scope of the basic presentation here.
How can I get my database passwords if mu manages them for me?
You can read them from Amazon's SSM ParameterStore:
aws ssm get-parameters --names mu-database-mu-wordpress-test-DatabaseMasterPassword --with-decryption aws ssm get-parameters --names mu-database-mu-wordpress-prod-DatabaseMasterPassword --with-decryption
If you use different environment names, you can list all the available parameters to find the right names:
aws ssm describe-parameters