So single EC2 instance is cool and all. But this is the cloud. So dispite that I have routly 3 visitors to my site (and one is probably a bot), let’s setup the infrastructure to scale.
Step one is to build and upload my docker container to ECR. (this does mean I’ll have to change all my ansible plays)
1
2
3
4
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin .dkr.ecr.us-west-2.amazonaws.com
docker build -t dans-homepage .
docker tag dans-homepage:latest .dkr.ecr.us-west-2.amazonaws.com/dans-homepage:latest
docker push .dkr.ecr.us-west-2.amazonaws.com/dans-homepage:latest
Step two is to create a cluster to hold everything
1
2
aws ecs create-cluster --cluster-name dans-homepage
aws ecs list-clusters
Next is to create a taks definition for my dan-homepage service.
1
2
aws ecs register-task-definition --cli-input-json file://`pwd`/dans-task-def.json
aws ecs list-task-definitions
The container task definition looks like this.
``` json : dans-task-def.json { “containerDefinitions”: [ { “name”: “dans-homepage”, “image”: “.dkr.ecr.us-west-2.amazonaws.com/dans-homepage:latest” “portMappings”: [ { “containerPort”: 80, “hostPort”: 80, “protocol”: “tcp” } ] } ], “memory”: “512”, “cpu”: “256”, “networkMode”: “awsvpc”, “family”: “http-server”, “requiresCompatibilities”: [ “FARGATE” ] }
1
2
3
4
5
6
Create the service itself. For this I'll first need the subnet Id's for my default VPC and the gourp id of my default secutity group.
```bash
aws ec2 describe-subnets | grep SubnetId
aws ec2 describe-security-groups | grep GroupId
Then I can create the service.
1
2
3
4
5
6
7
aws ecs create-service \
--cluster dans-homepage \
--service-name dans-homepage \
--task-definition dans-homepage:5 \
--desired-count 1 \
--launch-type "FARGATE" \
--network-configuration "awsvpcConfiguration={subnets=[subnet-0049d42d494e6563a,subnet-01753e2313b8a8532,subnet-0b19d4d273bd26f65,subnet-07b03a60d97f0b5eb],securityGroups=[sg-096e303e18dbb67bd], assignPublicIp=ENABLED}"
1
aws ecs list-services --cluster dans-homepage
Note that each time I update the docker image being uploaded, I’ll need to update the version number (and yes, I tried dans-homepage:latest. No luck)
Next is to get the public IP of the network interface.
1
2
3
aws ecs list-tasks --cluster dans-homepage # get the arn for my task
aws ecs describe-tasks --cluster dans-homepage --tasks "arn:aws:ecs:us-west-2::task/dans-homepage/d765a4dad128495ab8141228c61d2033" | grep eni # get the network interfacer for my task
aws ec2 describe-network-interfaces --network-interface-id "eni-0670deeb6ae5bbddb" | grep PublicIp # get the public IP address for this network interface attached to my service.
Test the ip address in the browser and ta-da! Site is up. Point cloudflare at that IP and we now have WAY more work that is every needed to tell you that I put too much work into this.
Deploy
The downsite is my workflow is now I have to redeploy the site manually.
- In my repo, run
JEKYLL_ENV=production bundle exec jekyll b
manually - Run
docker build -t dans-homepage .
to rebuild that image with the new post. - Push the image to ECR with docker
push .dkr.ecr.us-west-2.amazonaws.com/dans-homepage:latest
- Update the service with
aws ecs update-service --cluster dans-homepage --service dans-homepage --force-new-deployment
And then get the new public Ip of my interface and point cloudflare at that. With great fanciness comes great maintainance.