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
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:
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:
Permissions:
Environment Variables:
Workflow Steps:
?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
?
Author:
Noor Sabahi
Principal AI/ML Engineer
#GitHubActions #AWS #ECR #OIDC #Docker #CICD #DevOps #CloudSecurity #Automation #Kubernetes
?
?
?