Automating AWS Deployments with GitHub Actions : guide.

Tinashemadangure
6 min readAug 27, 2023

In today’s fast-paced software development landscape, automation plays a pivotal role in ensuring efficient and reliable deployment processes. GitHub Actions, a powerful CI/CD tool, offers seamless integration with AWS services like Amazon ECR (Elastic Container Registry) and Amazon ECS (Elastic Container Service). By combining GitHub Actions with AWS, developers can automate the building, pushing, and deployment of containerized applications, making the development lifecycle smoother and more streamlined.

This article dives into the process of setting up and configuring GitHub Actions to automate AWS deployments, focusing on building and deploying container images to Amazon ECR and updating task definitions in Amazon ECS. Let’s walk through the key steps and considerations involved in this process.

The article is based on Github actions available @ Github Docs.

I will be deploying my app which has code residing within my GitHub repository, and utilizing github actions .

Select the actions tab to set up github actions for code deployment for the gaming repo.

In the github actions market place will select the Deploy to amazon ecs.

*Prerequisites:**
Before you embark on configuring GitHub Actions for AWS deployments, ensure you have the following prerequisites in place:

  1. **Amazon ECR Repository:** Create an ECR repository to store your container images. Replace the `ECR_REPOSITORY` and `AWS_REGION` values in the workflow with your repository’s name and region.
Create a repo in Amazon ECR in this case named my “gaming” . Selected the Region “us-east-1”.

2. **Amazon ECS Infrastructure:** Set up the following:

a. Create an ecs cluster ,`ECS_CLUSTER`

Create an ECS cluster and named it “gaming-cluster”

b. Create ECS task definition.

Create an ECS task definition with a launch type “AWS Fargate” named it “gaming-Td
The other parameters of task definitions , “container name” and “ecs task role” are important.

c. Create an ecs service , `ECS_SERVICE`

The cluster we are using is the “gaming-cluster”.
We have named our service the “game-app-service.

3. **ECS Task Definition Configuration:** Store your ECS task definition as a JSON file in your repository. Make sure to follow the JSON format generated by the `aws ecs register-task-definition — generate-cli-skeleton` command. Update the `ECS_TASK_DEFINITION` and `CONTAINER_NAME` values in the workflow with the path to the JSON file and the container name, respectively.

admin@Tinas-Mac ~ % aws ecs describe-task-definition \
--task-definition gaming-Td \
--query taskDefinition > task-definition.json

The above will achieve a json file to be add to our .github/workflows/task-definition.json .

{
"taskDefinitionArn": "arn:aws:ecs:us-east-1:954975057:task-definition/gaming-Td:1",
"containerDefinitions": [
{
"name": "gaming",
"image": "954375057.dkr.ecr.us-east-1.amazonaws.com/gaming",
"cpu": 0,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"name": "gaming-80-tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-create-group": "true",
"awslogs-group": "/ecs/gaming-Td",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
}
}
],
"family": "gaming-Td",
"taskRoleArn": "arn:aws:iam::953545057:role/GitHub-demo",
"executionRoleArn": "arn:aws:iam::954549057:role/GitHub-demo",
"networkMode": "awsvpc",
"revision": 1,
"volumes": [],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "com.amazonaws.ecs.capability.task-iam-role"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512",
"registeredAt": "2023-08-27T07:29:43.114000+01:00",
"registeredBy": "arn:aws:iam::9543545057"
}

4. **GitHub Secrets:** Store your AWS IAM user access key as GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.

In the github repo ‘gaming’ under the settings tab update the secrets and variables for actions.
Add 2 secrets and their values `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`

Refer to the documentation for recommended IAM policies for this user and best practices for handling access key credentials.

**Workflow Overview:**
The GitHub Actions workflow provided automates the deployment process as follows:

1. **Build and Push Container Image:** Whenever there’s a push to the “main” branch, the workflow triggers. It builds the Docker container image and pushes it to the configured Amazon ECR repository.

2. **Update Task Definition and Deploy:** After the image is pushed, the workflow updates the ECS task definition to use the latest image. This updated task definition is then used to update the ECS service, effectively deploying the latest version of the application.

Below is the workflow with the updated env variables we derived from previous steps .

name: Deploy to Amazon ECS

on:
push:
branches: [ "main" ]

env:
AWS_REGION: us-east-1 # set this to your preferred AWS region, e.g. us-west-1
ECR_REPOSITORY: gaming # set this to your Amazon ECR repository name
ECS_SERVICE: game-app-service # set this to your Amazon ECS service name
ECS_CLUSTER: gaming-cluster # set this to your Amazon ECS cluster name
ECS_TASK_DEFINITION: .github/workflows/task_defination.json # set this to the path to your Amazon ECS task definition
# file, e.g. .aws/task-definition.json
CONTAINER_NAME: gaming # set this to the name of the container in the
# containerDefinitions section of your task definition

permissions:
contents: read

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}

- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true

Our github workflow will trigger the actions and achieve the below steps.

A successful deployment and the job run according to the workflow.

By navigating to the gaming cluster we created we can pick up the details for our deployment .

Our task overview will display the ip to access our app.

After extracting the ip we access the app in our browser.

By following the steps outlined in the provided workflow, developers can ensure that their applications are automatically built, tested, and deployed to AWS with every push to the main branch.

**Conclusion:**
Leveraging GitHub Actions to automate AWS deployments offers a streamlined and efficient approach to managing containerized applications. With proper setup and configuration, developers can significantly reduce the manual intervention required in the deployment process. By integrating GitHub Actions with AWS services like ECR and ECS, teams can achieve continuous integration and continuous deployment (CI/CD) practices, ensuring faster release cycles and higher software quality.

--

--