Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
terraform.*
.DS_Store
*.log
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM alpine:3.5
MAINTAINER "Titan Lien" <titan.lien@gmail.com>

ENV ANSIBLE_VERSION=2.2.2.0

RUN set -ex && \
buildDeps="python-dev build-base libffi-dev openssl-dev" && \
apk add --no-cache $buildDeps python py-pip ca-certificates bash tar && \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir ansible==${ANSIBLE_VERSION} && \
apk del --purge $buildDeps

CMD ["ansible"]
50 changes: 27 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Practical example on how to get a Wordpress running under an Amazon ECS Cluster
* [Terraform](https://www.terraform.io/)
* [Amazon ECS](https://aws.amazon.com/ecs/)
* [Amazon RDS](https://aws.amazon.com/es/rds/)
* [Amazon ELB](https://aws.amazon.com/elasticloadbalancing/)

## Requirements

Expand All @@ -25,61 +26,64 @@ To use this example you will need an [AWS](https://aws.amazon.com/es/) account a

1. Build the Wordpress container.

Packer will use a [base Docker image with Ansible](https://github.com/jfusterm/dockerfiles/blob/master/ansible/Dockerfile) to provision all the applications needed to run a Wordpress. The result will be saved into a container named `jfusterm/wp-packer` with a version tag `4.4.2`.
Packer will use a [base Docker image with Ansible](https://github.com/titanlien/wordpress-ecs/blob/master/Dockerfile) to provision all the applications needed to run a Wordpress. The result will be saved into a container named `titanlien/wp-packer` with a version tag `4.7.3`.

**Note 1**: If you want to change the image tag you have to change it in `wp-packer.json` and `wordpress.json`.

**Note 2**: Packer will push the image to [Dockerhub](https://hub.docker.com/) automatically.

**Note**: If you want to change the image tag you have to change it in `wp-packer.json` and `wordpress.json`.

```
# packer build wp-packer.json
# packer build -var 'DOCKER_PASSWD=[SECURITY]' wp-packer.json
```

2. Push the container to [Dockerhub](https://hub.docker.com/)

Check that the image is ready.

```
# docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
jfusterm/wp-packer 4.4.2 60bfb4ef7e9d 3 hours ago 138.2 MB
REPOSITORY TAG IMAGE ID CREATED SIZE
titanlien/wp-packer 4.7.3 334cf6396987 16 hours ago 155 MB
```

Then you can push it to Dockerhub.

```
# docker login
# docker push jfusterm/wp-packer:4.4.2
2. Deploy all the infrastructure needed on AWS using Terraform.
3. Create two amazon roles, *qq-ecs-role* and *qq-ec2-role*, to handle the EC2 resource.
4. Launching stack by following command.
```bash
$ env TF_VAR_aws_access_key=$AWS_ACCESS_KEY TF_VAR_aws_secret_key=$AWS_SCERET_KEY TF_VAR_key_name=titan@MBA terraform apply
```

3. Deploy all the infrastructure needed on AWS using Terraform.

```
# terraform apply
```

Once deployed, Terraform will display the ECS Container Instances public IPs and the [ELB](https://aws.amazon.com/es/elasticloadbalancing/) URL that will distribute the traffic across the different Wordpress container instances.
Once deployed, Terraform will print out the ECS Container Instances public IPs and the [ELB](https://aws.amazon.com/es/elasticloadbalancing/) URL that will distribute the traffic across the different Wordpress container instances.

The RDS connection parameters will be passed on runtime to the Wordpress containers via environment variables.

4. Once not needed, we can remove all the AWS infrastructure:
5. Upstream container log to cloudwatch awslogs.

6. Once not needed, we can remove all the AWS infrastructure:

```
# terraform destroy

```bash
$ terraform destroy
```

## Considerations

This example uses a basic and simple approach to get a ready to use Wordpress using different technology. Further modifications will be done to get a fully automated, scalable and high available Wordpress. Some thoughts:

* Wrap all the steps in a single script: build the container, push the container to Dockerhub or a private registry and finally deploy all the infrastructure on AWS.
* ~~Automate Wordpress installation when the first instance is launched. **Note**: Currently the ELB won't work properly due to the health-checks configuration until Wordpress is installed from one of the Worpress instances.~~
* Distribute the ECS Container Instances across different availability zones and route the traffic using the ELB among them.
* Decouple Nginx and PHP-FPM in separate containers so can be scaled independently.
* Sending log to [ELK](https://www.elastic.co/products) or [Amazon Elasticsearch Service](https://aws.amazon.com/elasticsearch-service/).
* Setting [cloudwtach](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/mon-scripts.html) to monitor CPU, memory and network traffic.
* Use a shared or distributed storage system to persist Wordpress' data. Examples:
* [Amazon EFS](https://aws.amazon.com/efs/)
* [GlusterFS](https://www.gluster.org/)
* [Flocker](https://docs.clusterhq.com/en/latest/docker-integration/)
* Remove the RDS single point of failure. Examples:
* Deploy RDS on [Multi-AZ](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html)
* Use [Percona XtraDB Cluster](https://www.percona.com/software/mysql-database/percona-xtradb-cluster)

## Sample ELB page
![alt text][demo]

[demo]: https://github.com/titanlien/wordpress-ecs/raw/master/raw/images/wp-demo.png "Wordpress Title Text 2"
2 changes: 1 addition & 1 deletion packer/ansible/roles/php-fpm/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
- name: PHP-FPM | Installation
apk:
name=php-fpm,php-mysql,php-opcache
name=php5-fpm,php5-mysql,php5-opcache
state=present
update_cache=yes

Expand Down
4 changes: 2 additions & 2 deletions packer/ansible/roles/wordpress/files/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

cd /usr/share/nginx/html/wordpress
cd /var/lib/nginx/html/wordpress

if ! [ -e wp-config.php ] && [ -e wp-config-sample.php ]; then

Expand Down Expand Up @@ -33,4 +33,4 @@ mv wp-config-sample.php wp-config.php

cd /

exec "$@"
exec "$@"
2 changes: 1 addition & 1 deletion packer/ansible/roles/wordpress/files/install-wp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

EC2_PUBLIC_IP=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
EC2_PUBLIC_IP=$(curl -s http://whatismyip.akamai.com/)
WP_INSTALL_URL="http://$EC2_PUBLIC_IP/wp-admin/install.php?step=2"

# Wait random time between 1s and 15s so the container with the lowest wait installs Wordpress, not all at once.
Expand Down
7 changes: 4 additions & 3 deletions packer/ansible/roles/wordpress/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
url=https://wordpress.org/wordpress-{{ wordpress_version }}.tar.gz
dest=/wordpress.tar.gz
checksum=md5:{{ wordpress_md5 }}
validate_certs=no # Alpine 3.3 doesn't recognize Godaddy's CA.
validate_certs=yes

- name: Wordpress | Unarchive
unarchive:
src=/wordpress.tar.gz
dest=/usr/share/nginx/html
dest=/var/lib/nginx/html
remote_src=yes

- name: Wordpress | Set permissions
file:
path=/usr/share/nginx/html/wordpress
path=/var/lib/nginx/html/wordpress
owner=nginx
group=nginx
state=directory
Expand Down
4 changes: 2 additions & 2 deletions packer/ansible/roles/wordpress/vars/main.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
wordpress_version: "4.5"
wordpress_md5: "6beda5bee679ddff61cb8e2e163f23bf"
wordpress_version: "4.7.3"
wordpress_md5: "044729d30b720809f19e14ece49e119b"
52 changes: 27 additions & 25 deletions packer/wp-packer.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
{
"builders": [
"variables": {
"docker_passwd": ""
},
"builders": [
{
"type": "docker",
"image": "jfusterm/ansible",
"image": "titanlien/ansible:3.5",
"commit": true
}
],
"provisioners": [
{
"type": "ansible-local",
"playbook_dir": "ansible",
"playbook_file": "ansible/wordpress.yml"
}
],
"post-processors": [
[
{
"type": "docker-tag",
"repository": "jfusterm/wp-packer",
"tag": "4.5"
},
{
"type": "docker-push",
"login": "true",
"login_username": "jfusterm",
"login_password": "",
"login_email": "joan.fuster@gmail.com"
}
]
]
"provisioners": [
{
"type": "ansible-local",
"playbook_dir": "ansible",
"playbook_file": "ansible/wordpress.yml"
}
],
"post-processors": [
[
{
"type": "docker-tag",
"repository": "titanlien/wp-packer",
"tag": "4.7.3"
},
{
"type": "docker-push",
"login": "true",
"login_username": "titanlien",
"login_password": "{{user `docker_passwd`}}"
}
]
]
}
Binary file added raw/images/wp-demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions terraform/ec2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ resource "aws_instance" "ecs-instance01" {
subnet_id = "${aws_subnet.wp-public-tf.id}"
key_name = "${var.key_name}"
associate_public_ip_address = true
iam_instance_profile = "ecsInstanceRole"
iam_instance_profile = "${aws_iam_instance_profile.web_instance_profile.id}"
security_groups = ["${aws_security_group.wp-ecs-sg-tf.id}"]
user_data = "#!/bin/bash\necho ECS_CLUSTER=${aws_ecs_cluster.default.name} > /etc/ecs/ecs.config"
tags {
Name = "ecs-instance01"
}
depends_on = ["aws_iam_instance_profile.web_instance_profile"]
}

resource "aws_instance" "ecs-instance02" {
Expand All @@ -22,7 +23,7 @@ resource "aws_instance" "ecs-instance02" {
subnet_id = "${aws_subnet.wp-public-tf.id}"
key_name = "${var.key_name}"
associate_public_ip_address = true
iam_instance_profile = "ecsInstanceRole"
iam_instance_profile = "${aws_iam_instance_profile.web_instance_profile.id}"
security_groups = ["${aws_security_group.wp-ecs-sg-tf.id}"]
user_data = "#!/bin/bash\necho ECS_CLUSTER=${aws_ecs_cluster.default.name} > /etc/ecs/ecs.config"
tags {
Expand Down
Loading