GitHub
CI/CD Simple pipeline
Application Pipeline
Technical details for server admin of the Application workflow:

Fail-over scenarios

Created a very simple Docker image --> https://hub.docker.com/r/cr3w/simple-website this image exists for failover and just updates with GitHub actions on every PR.
Once we make an update to the version ( local, or by a PR to GitHub --> https://github.com/stefanogram/docker-aws [needs and approval], we push the change to GitHub, and with GitHub actions (https://github.com/stefanogram/docker-aws/actions)
we push the new version to the Docker Hub --> https://hub.docker.com/r/cr3w/simple-website
will use AWS Elastic Container Registry as a main source for now. Will have to create a new repo ( region us-east-02 https://us-east-2.console.aws.amazon.com/ecr/repositories?region=us-east-2
We will push any updates on the app from GitHub to the ECR using GitHub actions
Then will use ECS -Elastic Container Service for deploying the Docker container into EC2( will create task definition).
ECR
we create a new ( private ) repo https://us-east-2.console.aws.amazon.com/ecr/repositories?region=us-east-2
Authenticate Docker to ECR:
stefano@teras ~/D/DevOPS> aws ecr create-repository --repository-name simple-website --region us-east-2
{
"repository": {
"repositoryArn": "arn:aws:ecr:us-east-2:693505164922:repository/simple-website",
"registryId": "693505164922",
"repositoryName": "simple-website",
"repositoryUri": "693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website",
"createdAt": "2023-07-29T16:01:16+01:00",
"imageTagMutability": "MUTABLE",
"imageScanningConfiguration": {
"scanOnPush": false
},
"encryptionConfiguration": {
"encryptionType": "AES256"
}
}
}
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website
Tag the Docker image with ECR repo URI:
Now if you want to pull this local, as you might now need to do some changes, and push to AWS instance later, you need to make sure to clone the repo local from GitHub
Pull the image local in your machine (or from GitHub or from Docker Hub ) and tag it.
docker pull cr3w/simple-website:latest
docker tag cr3w/simple-website:latest 693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website:latest
Then we need to push the image to ECR:
docker push 693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website:latest
Verify that the image is in our ECR repository:
stefano@teras ~/D/D/d/simple-website> aws ecr describe-images --repository-name simple-website --region us-east-2
{
"imageDetails": [
{
"registryId": "693505164922",
"repositoryName": "simple-website",
"imageDigest": "sha256:dbe393a5ab2109eab62ec8ab2bb467462e7214b132ad257c381f036b8bf3ee17",
"imageTags": [
"latest"
],
"imageSizeInBytes": 64690050,
"imagePushedAt": "2023-07-29T16:23:48+01:00",
"imageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
"artifactMediaType": "application/vnd.docker.container.image.v1+json"
}
]
}
We need to make sure here that when we push new image versions on Docker Hub to have the latest
tag as ECR is listening the "latest" tag to get the most up to date version.
You can always revert previous image with pushing older versions example Tag=1.0.0
This will revert the Docker image to ECR which then will push the image to AWS and will revert the updates have made sure once we make an update to GitHub, we also update the docker hub.
Also we need to make sure that we have already created Role with permission: `AmazonEC2ContainerRegistryReadOnly` for our instances to be able to ready the Docker ECR images.
We define that in our cloudformation.yml file we add the IamInstanceProfile
property to our AWS::AutoScaling::LaunchConfiguration
This is a Global configuration created here: https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-2#/roles/details/EC2_ECR?section=permissions
Here is our full cloudformation.yml
Parameters:
InstanceType:
Description: micro ec2 instance with health checks
Type: String
Default: t2.micro
KeyName:
Description: stefano's keypair
Type: AWS::EC2::KeyPair::KeyName
Default: stefano-us-east-2
ImageId:
Description: aws Image ID for this instance
Type: AWS::EC2::Image::Id
Default: ami-024e6efaf93d85776
RoleName:
Description: IAM Role to allow EC2 instances to access ECR
Type: String
Default: EC2_ECR
Resources:
MyLaunchConfiguration:
Type: "AWS::AutoScaling::LaunchConfiguration"
Properties:
InstanceType: !Ref InstanceType
ImageId: !Ref ImageId
KeyName: !Ref KeyName
SecurityGroups:
- "sg-a7f988c5"
IamInstanceProfile: !Ref RoleName
UserData:
Fn::Base64: !Sub |
#!/bin/bash
sudo apt-get update -y
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common unzip
curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce
sudo systemctl start docker
sudo systemctl enable docker
$(aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 693505164922.dkr.ecr.us-east-2.amazonaws.com)
sudo docker pull 693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website:latest
sudo docker run -d -p 80:80 693505164922.dkr.ecr.us-east-2.amazonaws.com/simple-website:latest
MyAutoScalingGroup:
Type: "AWS::AutoScaling::AutoScalingGroup"
Properties:
AvailabilityZones:
- "us-east-2a"
- "us-east-2b"
MinSize: "2"
MaxSize: "4"
DesiredCapacity: "2"
HealthCheckType: EC2
LaunchConfigurationName: !Ref MyLaunchConfiguration
TargetGroupARNs:
- !Ref MyTargetGroup
MyLoadBalancer:
Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
Properties:
Subnets:
- "subnet-feced596"
- "subnet-c7dc8dbd"
- "subnet-52d9611e"
SecurityGroups:
- "sg-a7f988c5"
MyTargetGroup:
Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
Properties:
HealthCheckIntervalSeconds: 30
HealthCheckPath: "/"
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 5
UnhealthyThresholdCount: 2
Matcher:
HttpCode: '200'
Port: 80
Protocol: HTTP
VpcId: "vpc-73cb3818"
TargetType: "instance"
MyListener:
Type: "AWS::ElasticLoadBalancingV2::Listener"
Properties:
LoadBalancerArn: !Ref MyLoadBalancer
Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupArn: !Ref MyTargetGroup
Improvements of the cloudformation.yml can be tracked here this is only for testing purposes do not use in production.
Finally we will use watchtower in Docker: https://containrrr.dev/watchtower/ to track updates on our ECR image, and pull it to the EC2 instances.
Watchtower is an application that will monitor our running Docker containers and watch for changes to the images that those containers were originally started from. If watchtower detects that an image has changed, it will automatically restart the container using the new image.
Troubleshooting Watchtower:
sudo docker logs --follow watchtower
Resources:
GitHub repo: https://github.com/stefanogram/docker-aws
Docker Hub: https://hub.docker.com/repository/docker/cr3w/simple-website/general
AWS pipeline ( EC2 Cloudformation LBs Instances ): https://github.com/stefanogram/aws_pipeline
Actions
What this is doing?
LB apps:
To Do
Create fallback in case Docker Hub or GitHub are are not available. ❌
Create fallback and reroutes in case AWS is not available ( K8s cluster or Linode server fleet with CF tunnels ) ❌
Last updated
Was this helpful?