Deploy to AWS ECS using GitHub Actions

I created a simple hands-on lab to deploy containers to Amazon AWS Elastic Container Services (ECS) using GitHub Actions.

The hands-on is available on GitHub. It’s better to switch there if you want to do it as it has all the links. It is easier to have the steps inside the fork. But the hands-on focuses on getting the thing deployed. In this post I want to highlight some of the gotchas for the workflow.

Prerequisites

I assume that you already have a AWS and a GitHub account. The registration is not included. If you leave all the defaults in AWS than you will use the free tier.

Pricing

If you use the Getting Started with Amazon Elastic Container Service (Amazon ECS) using Fargate wizard, ECS will not be free. The documentation is not very clear about this. But I had three cluster running for one week and I only had to paid $6.

So the costs are not high. But make sure to delete your clusters and load balancers if you are done.

See pricing for more information.

Infrastructure as Code

I wanted to have an easy script to deploy and clean up the resources in AWS like I have in my Deploy to Azure App Service tutorial. Unfortunately, I was not able not find something that did not involve tons of json to configure. If you have a source, please leave a comment or contact me on Twitter.

The workflow

I split up the workflow into a build and a deploy stage. This enables you to easily add environments and more stages.

Staged deployment to AWS

For this to work, you must pass the image name from the build job to the deploy job. You can use job outputs for that:

jobs:
  Build:
    runs-on: ubuntu-latest
    outputs:
      image: ${{ steps.build-image.outputs.image }}

The problem is, that the Configure AWS Credentials action masks your account id per default. But the account id is part of your ECR registry URL. This will result in the following warning when you try to pass the image name to the next job:

Warning: Skip output 'image' since it may contain secret.

To avoid this you have to prevent the action from masking your account id:

- 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 }}
    mask-aws-account-id: no

This is not very intuitive since the image name has nothing to do with that task. But GitHub inspects the value of the secret and detects the same value in the url and masks it.

Without the mask, you can build and push the image to ECR and set the output variable:

- name: Build, tag, and push image to Amazon ECR
  id: build-image
  env:
    ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
    IMAGE_TAG: ${{ github.sha }}
  working-directory: ch9_release/src/Tailwind.Traders.Web
  run: |
    imagename=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
    echo "Build and push $imagename"
    docker build -t $imagename .
    docker push $imagename
    echo "::set-output name=image::$imagename"

In the next job you can than read the value from the needs context, update the json task definition and perform the deployment to ECS:

- 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: ${{ needs.Build.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

Conclusion

It took me some time to figure this out. The documentation on GitHub is not very helpful for the AWS part and it also does build and deployment in a single job. I also did not find simple ways to deploy ECS. So I thought I share my findings here. If you know better ways to deploy and clean up the resources on AWS, make sure to let me know.

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s