Securely Deploy Docker Images to Amazon ECR with GitHub Actions & OIDC

Securely Deploy Docker Images to Amazon ECR with GitHub Actions & OIDC

In modern cloud-native development, securely building and deploying containerized applications is a top priority. Amazon Elastic Container Registry (ECR) provides a scalable and secure way to store and manage Docker images, while GitHub Actions (GHA) enables seamless CI/CD automation.

In this guide, we’ll walk through how to?build, tag, and push?Docker images to ECR using?GitHub Actions, leveraging the?OpenID Connect (OIDC) provider?and?IAM roles?for a secure, passwordless authentication process. By eliminating long-lived AWS credentials and adopting OIDC-based authentication, we enhance security while streamlining deployments. Let’s dive in!?

?Content

  • Creating an ECR Repository
  • Securely Storing ECR and AWS Credentials in GitHub Secrets using Terraform
  • Creating an IAM Role for GitHub Actions
  • Configuring GitHub Actions Workflow
  • Creating GitHub Actions Workflow
  • Running and Verifying the Workflow Execution
  • Conclusion

Create an ECR Repository

I created public Amazon ECR repo using Terraform as shown in the code below.

I used "terraform-aws-modules/ecr/aws" module. Using a module simplifies infrastructure management by promoting reusability, consistency, and maintainability while reducing code duplication.

?module "ecr" {
  source  = "terraform-aws-modules/ecr/aws"
  version = "~> 2.3.1"

  repository_name = "${var.ecr_repository}"
  repository_type = "public"

  repository_lifecycle_policy = jsonencode({
    rules = [
      {
        action = {
          type = "expire"
        }
        description  = "lifecycle"
        rulePriority = 1
        selection = {
          countNumber = 5
          countType   = "imageCountMoreThan"
          tagStatus   = "untagged"
        }
      }
    ]
  })
}        


Securely Storing ECR and AWS Credentials in GitHub Secrets

In this step, we push the ECR repo name, and aws account ID as secrets to GitHub to allow GitHub later to use them while pushing the image to Amazon ECR.

First, I want to test writing secrets to GitHub manually using CLI.

To do this step, you need GitHub CLI installed because it will execute “gh secret set AWS_ACCOUNT_ID”

Install gh on mac

brew install gh
gh -–version        

Authenticate to GitHub CLI

gh auth login?        

Once authenticated, verify it

?gh auth status        

Test setting a secret manually

echo "test-value" | gh secret set TEST_SECRET
gh secret lit        

Check authenticated GithHub account

gh auth status        

Login

Gh auth login?        

Login and Out

To logout from one account in order to login another

gh auth logout        


Write Amazon Account ID and ECR Repository Name to GitHub Secrets

I added this terraform resources that writes values to GitHub Secrets.

This Terraform code defines a null_resource that uses a local-exec provisioner to execute GitHub CLI (gh secret set) commands, storing AWS and ECR-related values as GitHub repository secrets. The values are dynamically fetched from Terraform outputs, ensuring they are up-to-date.

resource "null_resource" "set_github_secrets" {
  
  provisioner "local-exec" {
    command = <<EOT
      gh secret set AWS_ACCOUNT_ID --body="$(terraform output -raw aws_account_id)"
      gh secret set AWS_REGION --body="$(terraform output -raw aws_region)"
      gh secret set ECR_REPOSITORY --body="$(terraform output -raw ecr_repo_name)"
      gh secret set ECR_PUBLIC_REGISTRY_ALIAS --body="$(terraform output -raw ecr_public_registry_alias)"
      gh secret set DOCKER_IMG_TAG --body="$(terraform output -raw docker_img_name)"
    EOT
  }

  depends_on = [ module.ecr ]
}
        


Create ECR Role

?Follow the steps below to create Web Identity role for GitHub.

Create a role (YOUR_GITHUB_ACTIONS_ROLE) in AWS and grant it the necessary permissions for GitHub Actions, follow these steps:

Choose "Web identity"?as the trusted entity type.


Identity provider: Select?GitHub. Currently, no GitHub Provider, so click “Create new”

For the URL set:

https://token.actions.githubusercontent.com        

for audience, set:

sts.amazonaws.com        

then, click “Add provider”. Provider is created successfully as you see in the screenshot below:

Now, if you go back to the Role section and select OpenID Connect again, you will see GitHub listed as a provider, allowing you to create a web identity role based on it.


?

Attach permissions

You'll need to attach the following policies to the role:

  • AmazonS3ReadOnlyAccess?(if you need to pull artifacts from S3 in your GitHub Actions)
  • AmazonEC2ContainerRegistryPowerUser?(for building and pushing container images to ECR): Provides full access to Amazon EC2 Container Registry repositories, but does not allow repository deletion or policy changes.
  • Optional: AmazonEKSClusterPolicy?(if you're interacting with EKS)


Add Trust Policy to the Role

In the console, click on Edit Trust Relationship and adjust it to allow your unique GitHub organization, repository, and branch to assume the role.?


{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::YOUR-ACCOUNT-ID:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:YOUR-REPOSITORY-NAME:*"
                }
            }
        }
    ]
}        


GitHub Workflow Code Explained

The GitHub Actions workflow we want to create mainly to?build, tag, and push?a Docker image to?Amazon Public ECR securely using?OIDC authentication. Here's a breakdown of each step for the code provided below:

Triggers:

  • Runs?manually?(workflow_dispatch) or on a?push to the?main?branch?if files inside?dynamic-website/kuberenetes_tutorial/?are modified.

Permissions:

  • Grants?id-token: write?permission, enabling GitHub to authenticate with AWS via OIDC.
  • Grants?contents: read?to access the repository’s contents.

Environment Variables:

  • Uses?AWS region,?ECR public registry alias,?ECR repository name, and?Docker image tag?from?GitHub Secrets (The values we wrote to GH secrets using terraform resource above).
  • Defines the IAM role (The one we created earlier) for secure authentication.

Workflow Steps:

  • Checkout Code: Pulls the latest code from the repository.
  • Configure AWS Credentials: Uses GitHub’s OIDC authentication to assume the AWS IAM role without storing long-lived credentials.
  • Login to Public ECR: Retrieves an authentication token and logs in to the?public ECR registry.
  • Build ,Tag & Push Docker Image: 1) Builds a Docker image from the?dynamic-website/kuberenetes_tutorial?directory. 2) Tags the image using the?public ECR repository alias and the predefined image tag. 3) Pushes the image to?Amazon Public ECR.

?name: Build and Deploy to Public ECR

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - 'dynamic-website-folder-name/**'  # Watches this folder for changes

permissions:
  id-token: write  # Required for OIDC authentication with AWS
  contents: read

jobs:
  build-and-deploy:
    name: Build & Push Docker Image to Public ECR
    runs-on: ubuntu-latest

    env:
      AWS_REGION: us-east-1  
      ECR_PUBLIC_REGISTRY_ALIAS: ${{ secrets.ECR_PUBLIC_REGISTRY_ALIAS }}  
      ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}  
      IMAGE_TAG: ${{ secrets.DOCKER_IMG_TAG }}  # Timestamp-based tag
      ROLE_NAME: GITHUB-ACTIONS-K8S-TUTORIAL-ROLE

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ env.ROLE_NAME}}
          aws-region: ${{ env.AWS_REGION }}

      - name: Login to Public Amazon ECR
        id: login-ecr
        run: |
          aws ecr-public get-login-password --region ${{ env.AWS_REGION }} | \
          docker login --username AWS --password-stdin public.ecr.aws/${{ env.ECR_PUBLIC_REGISTRY_ALIAS }}

      - name: Build, Tag & Push Docker Image
        run: |
          docker build -t public.ecr.aws/$ECR_PUBLIC_REGISTRY_ALIAS/$ECR_REPOSITORY:$IMAGE_TAG ./dynamic-website/kuberenetes_tutorial
          docker push public.ecr.aws/$ECR_PUBLIC_REGISTRY_ALIAS/$ECR_REPOSITORY:$IMAGE_TAG
        

This setup ensures?secure and automated deployment?to Amazon ECR?without requiring AWS credentials?in GitHub Secrets, leveraging?OIDC authentication?for enhanced security

Run GitHub Actions Workflow

Now, it is time to test the setup above, go to your repo, and from actions tab, select the workflow and click “run workflow” after selecting the right branch if it is not main.



Gtihub starts running the workflow, it takes few seconds for the new workflow to show up.

Once it is done, we see that the execution was successful.

To verify the successful build and push of the docker image to ECR, we go to the reso created using terraform to find a new image was pushed! Great! The workflow build, taged and pushed the image successfully to ECR!

?Conclusion

By leveraging?GitHub Actions?with?OIDC authentication, we have securely automated the process of building, tagging, and pushing Docker images to?Amazon Public ECR?without storing long-lived AWS credentials. Using?Terraform, we streamlined the creation of the?ECR repository?and?IAM role, ensuring a scalable and repeatable setup. This approach enhances security, simplifies authentication, and integrates seamlessly into modern?cloud-native CI/CD pipelines. With this workflow in place, deployments to ECR are now more efficient, secure, and fully automated

?

Code on GitHub: https://github.com/Tiger4Code/K8s-Tutorial-Django-Postgres-Webapp

Author:

Noor Sabahi

Principal AI/ML Engineer


#GitHubActions #AWS #ECR #OIDC #Docker #CICD #DevOps #CloudSecurity #Automation #Kubernetes


?

?

?

要查看或添加评论,请登录

Noor S.的更多文章

社区洞察

其他会员也浏览了