Deploying a container from GitHub Actions to AWS Elastic Container Registry (ECR) and AWS Elastic Container Service (ECS) can be done securely using OpenID Connect (OIDC). This method eliminates the need to store long-lived AWS credentials, making your CI/CD pipeline more secure. This guide will walk you through setting up OIDC authentication for GitHub Actions to push Docker images to AWS ECR.
Step 1: Enable OIDC Provider in AWS
- Sign in to AWS Console and navigate to IAM.
- Go to Identity providers > Add provider.
- Select OpenID Connect as the provider type.
- Enter the Provider URL:
https://token.actions.githubusercontent.com
- Click Get thumbprint (AWS will auto-populate this).
- Under Audience, enter:
https://github.com
- Click Add provider.
Step 2: Create an IAM Role for GitHub Actions
- In the AWS Console, go to IAM > Roles > Create Role.
- Select Web identity as the trusted entity type.
- Choose the OIDC provider you just created.
- Under 'Audience' enter https://github.com
- Under 'GitHub organization' enter your .
- Click Next.
- Under 'Name' enter github-role
- Click Create
Step 3: Attach Policies for ECR and ECS Access
- create a custom policy for more control
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:DescribeRepositories",
"ecr:CreateRepository",
"ecr:ListImages",
"ecr:BatchDeleteImage"
],
"Resource": "*"
}
]
}
- Click Next, then give the policy a name (e.g., GitHubActionsECR).
- Click Create policy. Add another policy name githubECS for ECS Update
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:UpdateService",
"ecs:DescribeServices"
],
"Resource": [
"<ARN of ECS service 1",
"<ARN of ECS service 2",
"<ARN of ECS service n"
]
}
]
}
Step 4: Update Trust PolicyModify the trust policy to allow GitHub Actions to assume this role:
- Go to IAM > Roles > Select your role (GitHubActionsECR).
- Click Trust relationships > Edit trust policy.
- Replace the existing policy with:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "https://github.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:<GITHUB_ORG_OR_USER>/<REPO_NAME>:*"
}
}
}
]
}
(Replace with your AWS account ID)
(Replace / with your GitHub organization and repository name)
- Click Update policy.
Step 5: Configure GitHub Actions Workflow In your GitHub repository:
Go to Settings > Secrets and variables > Actions ->Add new repository secret:
Name: AWS_DB_URL
Value: AWS RDS full path for example postgres://db_username:password@rds instance name:5432/DB nameName: AWS_ECR_URI
Value: ECS repo path for example AWS_ AccountID.dkr.ecr.us-east-2.amazonaws.com/backend-microservices/user-service-stageName: AWS_REGION
Value: us-east-2Name: AWS_ROLE_ARN
Value: The ARN of the IAM role you created (found in AWS IAM).
Step 6: Update GitHub Actions Workflow (.github/workflows/deploy.yml)
Modify your workflow YAML file to assume the IAM role:
name: Deploy services to Stage AWS ECR and ECS
on:
push:
branches:
- stage
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.23
- name: Install dependencies
run: go mod tidy
- name: Run Integration Tests
run: go test -v ./integration_test/...
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
role-session-name: GitHubActionsSession
aws-region: ${{ secrets.AWS_REGION}}
audience: https://github.com
- name: Load Environment Variables
run: |
cat .env_stage.example >> $GITHUB_ENV
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build Docker Image for user-service
run: |
docker build \
--build-arg logLevelEnvVar=${LOG_LEVEL} \
--build-arg databaseURLEnvVar=${{secrets.AWS_DB_URL}} \
--build-arg portEnvVar=${PORT} \
--build-arg dBEnvVar=${DB} \
--build-arg dBMaxIdleEnvVar=${DB_MAX_IDLE} \
--build-arg dBMaxOpenEnvVar=${DB_MAX_OPEN} \
--build-arg dBMaxLifeTimeEnvVar=${DB_MAX_LIFE_TIME} \
--build-arg dBMaxIdleTimeEnvVar=${DB_MAX_IDLE_TIME} \
--build-arg zapConf=${ZAP_CONF} \
--build-arg gormConf=${GORM_CONF} \
--build-arg pprofEnable=${PPROF_ENABLE} \
-t ${{secrets.AWS_ECR_URI}}user-service-stage:latest \
-f service/user_service/Dockerfile \
.
docker push ${{secrets.AWS_ECR_URI}}user-service-stage:latest
- name: Deploy user-service to AWS ECS
run: |
aws ecs update-service --cluster cluster-backend-microservice --service service-user --force-new-deployment
Step 7: Test the Workflow
- Push a commit to the repository.
- Navigate to Actions in GitHub and verify that the workflow runs successfully.
- Your Docker image should now be pushed to Amazon ECR and ECS
Conclusion
Now your GitHub Actions workflow can push images to AWS ECR and ECS without requiring long-lived AWS credentials. This setup is more secure and efficient, enabling seamless container deployments from GitHub to AWS. 🎉
Top comments (1)
Excellent Post