A simple web application which serves different content according to a given environment variable.
Used for testing micro-services architectures.
Image is available at Dockerhub - unfor19/docker-cats
Available APP_NAME:
- baby
- green
- dark
docker run --name cats --rm -p 8080:8080 -d -e APP_NAME=baby unfor19/docker-cats
Change the author
docker run --name cats --rm -p 8080:8080 -d -e APP_NAME=dark -e FROM_AUTHOR=darker unfor19/docker-cats
View the app in local browser via http://localhost:8080
docker build -t unfor19/docker-cats .
Deploy in AWS behind Cloudflare - Expand/collapse
Before we even start, this is how the website should look like after a successful deployment - https://docker-cats-stg.meirg.co.il.
- Provision a least expensive architecture for mockups/proof of concepts; though still robust architecture. For example, I dodged the bullet of provisioning a Load Balancer (ALB/NLB).
- Publish an example of how to use GitHub Actions for building a Docker image, pushing it to a Docker registry (AWS ECR in my case) and performing a blue/green deployment to AWS ECS with ecs-deploy. I truly believe that this project can be converted from ECS to EKS or any other microservices orchestrator.
- I've created everything manually for "staging" via AWS Console. During the process, I've collected anything that I can (see ./resources) to ease the future move from "AWS Console to infrastructure as code (IaC)".
- CICD
- Network reachability - First, I added my IP address (ifconfig.me/ip) to the app's security group inbound rules. After checking that the app is reachable from my machine, I moved on to Cloudflare configuration (whitelist Cloudflare CIDR ranges)
Create the following AWS resources in the AWS console
- VPC (New VPC Experience) > Launch VPC Wizard > VPC, subnets, etc.
- Tick Auto-generate > Value:
docker-cats-stg
- Set VPC endpoints to None
- Tick Auto-generate > Value:
- ECS Cluster (Old ECS Experience)
- Click Create cluster
- Select Networking only
- Cluster Name:
docker-cats-stg
- Click Create
- ECS Task Definition
- Before we start - make sure the IAM role
ecsTaskExecutionRole
exists; The role is required by the AWS ECS Service to manage ECS Tasks, that includes pulling private images from ECR if necessary - Click Create new Task Definition
- Select FARGATE (Read more about AWS Fargate)
- Scroll down and click Configure via JSON
- Copy the contents of resources/app_ecs_task_definition.json and paste it in the JSON text area
- Find and replace
123456789012
with the relevant AWS account number - Click Create
- Before we start - make sure the IAM role
- ECS Service (Old ECS Experience)
- Click Create
- Launch Type:
FARGATE
- Task Definition:
docker-cats-stg
, Revision: select latest (previosuly created) - Select the previously created VPC
docker-cats-stg-vpc
- Service Name:
docker-cats-stg
- Number of tasks:
1
- Click Next step (Configure service)
- Cluster VPC:
docker-cats-stg
(previosuly created) - Subnets: select two public subnets
docker-cats-stg-subnet-public
- Review > Click Next step (Configure network)
- Click Next step (Set Auto scaling)
- Click Create Service (Review)
Allow inbound from Cloudflare only, according to the following list - https://www.cloudflare.com/ips-v4
- AWS Console > VPC > Security Groups > Search
docker-cats
and get the Security group ID - Run the following script to add Cloudflare's IP Ranges to the security group's inbound rules
# Requires AWS CLI and curl export \ SECURITY_GROUP_ID="sg-0d7209c7061234567" AWS_REGION="eu-west-1" ./scripts/set_inbound_cidr.sh
By default, Cloudflare proxies to known HTTPS ports.
I've set the app to listen on port 80
and allowed inbound access to port 80
only from Cloudflare's servers CIDR Ranges
Currently, there's an ECS Task which runs docker-cats
and has a public IP. To access the application, add your IP address to the Security Group inbound rules on port 80
to check if it's running properly
APP_PUBLIC_IP="123.123.123.123"
curl -L "$APP_PUBLIC_IP"
If you see <html lang="en">...
in the response, you're good to go.
Next up, mapping Cloudflare DNS record to the task's public IP with an A record. The downside, is that each time the ECS task restarts/stops, the public IP changes, we'll get to that.
- Login to Cloudflare
- Click on relevant domain
- Click DNS > Click Add record
- Name:
docker-cats-stg
- Value:
public IP of ECS Task
(keep the Proxied ON)
- Name:
- Click Rules > Click Create Page Rule
- URL:
docker-cats*.SELECTED_DOMAIN_NAME/*
(mySELECTED_DOMAIN_NAME
ismeirg.co.il
) - Click Add setting > SSL > Flexible (Cloudflare's SSL policies)
- URL:
Finally, docker-cats-stg.meirg.co.il
is mapped in Cloudflare to proxy traffic to the public IP of the ECS task.
Final result - https://docker-cats-stg.meirg.co.il
Cloudflare --> meets AWS security group rules --> ECS Task public IP
- app/images/baby.jpg source https://www.findcatnames.com/great-black-cat-names/ - img
- app/images/green.jpg source http://challengethestorm.org/cat-taught-love/ - img
- app/images/dark.jpg source https://www.maxpixel.net/Animals-Stone-Kitten-Cats-Cat-Flower-Pet-Flowers-2536662
Created and maintained by Meir Gabay
This project is licensed under the MIT License - see the LICENSE file for details