aws-cloudformation-task-ecs-deploy-gh
Scannednpx machina-cli add skill giuseppe-trisciuoglio/developer-kit/aws-cloudformation-task-ecs-deploy-gh --openclawAWS CloudFormation Task ECS Deploy with GitHub Actions
Comprehensive skill for deploying ECS containers using GitHub Actions CI/CD pipelines with CloudFormation infrastructure management.
Overview
Deploy containerized applications to Amazon ECS using GitHub Actions workflows. This skill covers the complete deployment pipeline: authentication with AWS (OIDC recommended), building Docker images, pushing to Amazon ECR, updating task definitions, and deploying ECS services. Integrate with CloudFormation for infrastructure-as-code management and implement production-grade deployment strategies.
When to Use
Use this skill when:
- Deploying Docker containers to Amazon ECS
- Setting up GitHub Actions CI/CD pipelines for AWS
- Configuring AWS authentication for GitHub Actions (OIDC or IAM keys)
- Building and pushing Docker images to Amazon ECR
- Updating ECS task definitions dynamically
- Implementing blue/green or rolling deployments
- Managing CloudFormation stacks from CI/CD
- Setting up multi-environment deployments (dev/staging/prod)
- Configuring private ECR repositories with image scanning
- Automating container deployment with proper security practices
Trigger phrases:
- "Deploy to ECS with GitHub Actions"
- "Set up CI/CD for ECS containers"
- "Configure GitHub Actions for AWS deployment"
- "Build and push Docker image to ECR"
- "Update ECS task definition from CI/CD"
- "Implement blue/green deployment for ECS"
- "Deploy CloudFormation stack from GitHub Actions"
Instructions
Follow these steps to set up ECS deployment with GitHub Actions:
- Configure AWS Authentication: Set up OIDC provider for GitHub Actions
- Create IAM Roles: Define roles for deployment actions
- Set Up ECR Repository: Create repository with image scanning
- Create ECS Cluster: Define cluster infrastructure
- Configure Task Definition: Set up task and container definitions
- Set Up ECS Service: Configure service with deployment strategy
- Create GitHub Workflow: Define CI/CD pipeline steps
- Configure Secrets: Store credentials securely in GitHub Secrets
For complete examples, see the EXAMPLES.md file.
Examples
The following examples demonstrate common deployment patterns:
Example 1: GitHub Actions Workflow
name: Deploy to ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: us-east-1
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
Example 2: Update Task Definition
- name: Update ECS Task Definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: my-service
cluster: my-cluster
Example 3: OIDC Provider Setup
OidcProvider:
Type: AWS::IAM::OIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- 6938fd4d98bab03faabd97ca34b7b5dbd06c4ee5
GitHubActionsRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: !Ref OidcProvider
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
token.actions.githubusercontent.com:aud: sts.amazonaws.com
token.actions.githubusercontent.com:sub: repo:my-org/my-repo:ref:refs/heads/main
For complete production-ready examples, see EXAMPLES.md.
Quick Start
Basic ECS Deployment Workflow
name: Deploy to ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-app
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Update task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy to ECS
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: true
Authentication Methods
OIDC Authentication (Recommended)
OpenID Connect (OIDC) provides secure, passwordless authentication between GitHub Actions and AWS.
Prerequisites:
- Create IAM role with trust policy for GitHub:
Type: AWS::IAM::Role
Properties:
RoleName: github-actions-ecs-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}: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:my-org/my-repo:*
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonECS_FullAccess
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
- Configure GitHub Actions workflow:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-role
aws-region: us-east-1
IAM Key Authentication (Legacy)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
Store credentials in GitHub repository secrets (Settings → Secrets and variables → Actions).
Build and Push to ECR
ECR Repository CloudFormation Template
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: my-app
ImageScanningConfiguration:
ScanOnPush: true
ImageTagMutability: IMMUTABLE
LifecyclePolicy:
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Keep last 30 images",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["v"],
"countType": "imageCountMoreThan",
"countNumber": 30
},
"action": {
"type": "expire"
}
}
]
}
Build and Push Step
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
${{ steps.login-ecr.outputs.registry }}/my-app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_DATE=${{ github.event.head_commit.timestamp }}
VERSION=${{ github.sha }}
Task Definition Management
Basic Task Definition
task-definition.json:
{
"family": "my-app-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "my-app",
"image": "PLACEHOLDER_IMAGE",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{
"name": "ENVIRONMENT",
"value": "production"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:my-app/db-password"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs",
"awslogs-create-group": "true"
}
}
}
]
}
Dynamic Task Definition Update
- name: Render task definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
id: render-task
with:
task-definition: task-definition.json
container-name: my-app
image: ${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
- name: Deploy task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: true
deploy_timeout: 30 minutes
ECS Deployment Strategies
Rolling Deployment (Default)
- name: Deploy to ECS (Rolling)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
wait-for-service-stability: true
CloudFormation Service Configuration:
ECSService:
Type: AWS::ECS::Service
Properties:
ServiceName: my-service
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
EnableECSManagedTags: true
PropagateTags: SERVICE
Blue/Green Deployment with CodeDeploy
- name: Deploy to ECS (Blue/Green)
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-task.outputs.task-definition }}
service: my-service
cluster: my-cluster
codedeploy-appspec: appspec.yaml
codedeploy-application: my-app
codedeploy-deployment-group: my-deployment-group
wait-for-service-stability: true
appspec.yaml:
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: my-app
ContainerPort: 8080
PlatformVersion: "1.4.0"
CloudFormation CodeDeploy Configuration:
CodeDeployApplication:
Type: AWS::CodeDeploy::Application
Properties:
ApplicationName: my-app
ComputePlatform: ECS
CodeDeployDeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
ApplicationName: !Ref CodeDeployApplication
DeploymentGroupName: my-deployment-group
ServiceRoleArn: !Ref CodeDeployServiceRole
DeploymentConfigName: CodeDeployDefault.ECSAllAtOnce
DeploymentStyle:
DeploymentType: BLUE_GREEN
DeploymentOption: WITH_TRAFFIC_CONTROL
AutoRollbackConfiguration:
Enabled: true
Events:
- DEPLOYMENT_FAILURE
- DEPLOYMENT_STOP_ON_ALARM
- DEPLOYMENT_STOP_ON_REQUEST
AlarmConfiguration:
Alarms:
- !Ref CPUPercentageAlarm
- !Ref MemoryPercentageAlarm
BlueGreenDeploymentConfiguration:
TerminateBlueInstancesOnDeploymentSuccess:
Action: TERMINATE
WaitTimeInMinutes: 5
DeploymentReadyOption:
ActionOnTimeout: CONTINUE_DEPLOYMENT
WaitTimeInMinutes: 0
LoadBalancerInfo:
TargetGroupPairInfoList:
- TargetGroups:
- Ref: BlueTargetGroup
- Ref: GreenTargetGroup
ProdTrafficRoute:
ListenerArns:
- !Ref ProductionListener
CloudFormation Integration
Update Stack from GitHub Actions
- name: Deploy CloudFormation stack
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-ecs \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides \
Environment=production \
DesiredCount=2 \
CPU=256 \
Memory=512 \
ImageUrl=${{ steps.login-ecr.outputs.registry }}/my-app:${{ github.sha }}
CloudFormation Stack with ECS Resources
ecs-stack.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Description: ECS Fargate Service with CloudFormation
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]
DesiredCount:
Type: Number
Default: 2
CPU:
Type: String
Default: '256'
Memory:
Type: String
Default: '512'
ImageUrl:
Type: String
Resources:
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: !Sub '${Environment}-cluster'
ClusterSettings:
- Name: containerInsights
Value: enabled
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Sub '${Environment}-task'
Cpu: !Ref CPU
Memory: !Ref Memory
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
TaskRoleArn: !GetAtt TaskRole.Arn
ContainerDefinitions:
- Name: my-app
Image: !Ref ImageUrl
PortMappings:
- ContainerPort: 8080
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref LogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
ECSService:
Type: AWS::ECS::Service
DependsOn: LoadBalancerListener
Properties:
ServiceName: !Sub '${Environment}-service'
Cluster: !Ref ECSCluster
TaskDefinition: !Ref TaskDefinition
DesiredCount: !Ref DesiredCount
LaunchType: FARGATE
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
SecurityGroups:
- !Ref ContainerSecurityGroup
AssignPublicIp: DISABLED
LoadBalancers:
- ContainerName: my-app
ContainerPort: 8080
TargetGroupArn: !Ref TargetGroup
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 100
DeploymentCircuitBreaker:
Enable: true
Rollback: true
HealthCheckGracePeriodSeconds: 60
Outputs:
ServiceURL:
Description: Service URL
Value: !Sub 'http://${LoadBalancer.DNSName}'
Stack Outputs for Cross-Stack References
Outputs:
ClusterName:
Description: ECS Cluster Name
Value: !Ref ECSCluster
Export:
Name: !Sub '${AWS::StackName}-ClusterName'
ServiceName:
Description: ECS Service Name
Value: !Ref ECSService
Export:
Name: !Sub '${AWS::StackName}-ServiceName'
TaskDefinitionArn:
Description: Task Definition ARN
Value: !Ref TaskDefinition
Export:
Name: !Sub '${AWS::StackName}-TaskDefinitionArn'
Best Practices
Security
- Use OIDC authentication instead of long-lived IAM keys
- Implement least privilege IAM roles with specific permissions
- Enable ECR image scanning on push
- Use AWS Secrets Manager for sensitive data
- Encrypt ECR repositories with KMS
- VPC endpoints for ECR and ECS without internet gateway
- Security groups restrict access to minimum required
IAM Role Permissions
ECSDeployRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Federated: !Sub 'arn:aws:iam::${AWS::AccountId}: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:${GitHubOrg}/${GitHubRepo}:*
Policies:
- PolicyName: ECSDeployPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ecs:DescribeServices
- ecs:DescribeTaskDefinition
- ecs:DescribeTasks
- ecs:ListTasks
- ecs:RegisterTaskDefinition
- ecs:UpdateService
Resource: !Sub 'arn:aws:ecs:${AWS::Region}:${AWS::AccountId}:*'
- Effect: Allow
Action:
- ecr:GetAuthorizationToken
- ecr:BatchCheckLayerAvailability
- ecr:GetDownloadUrlForLayer
- ecr:GetRepositoryPolicy
- ecr:DescribeRepositories
- ecr:ListImages
- ecr:DescribeImages
- ecr:BatchGetImage
- ecr:InitiateLayerUpload
- ecr:UploadLayerPart
- ecr:CompleteLayerUpload
- ecr:PutImage
Resource: !Sub 'arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/${ECRRepositoryName}'
- Effect: Allow
Action:
- cloudformation:DescribeStacks
- cloudformation:CreateStack
- cloudformation:UpdateStack
- cloudformation:DescribeStackEvents
Resource: !Sub 'arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${CloudFormationStackName}/*'
Performance
- Docker layer caching with GitHub Actions cache
- Multi-stage builds to minimize image size
- Parallel deployments across multiple environments
- Fargate Spot for cost savings on non-critical workloads
- CloudWatch Logs with appropriate retention policies
Cost Optimization
- ECR lifecycle policies to clean up old images
- Fargate Spot instances for development/testing
- Right-sized task CPU and memory
- Auto-scaling based on metrics
- Scheduled scaling for predictable traffic patterns
Multi-Environment Deployments
name: Deploy to ECS
on:
push:
branches: [main, staging, develop]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-ecs-${{ matrix.environment }}
aws-region: us-east-1
- name: Deploy to ${{ matrix.environment }}
run: |
aws cloudformation deploy \
--template-file infrastructure/ecs-stack.yaml \
--stack-name my-app-${{ matrix.environment }} \
--parameter-overrides \
Environment=${{ matrix.environment }} \
ImageUrl=${{ steps.build-image.outputs.image-url }}
Monitoring and Observability
- CloudWatch Container Insights for ECS metrics
- Application logs centralized in CloudWatch Logs
- Health checks with proper grace periods
- CloudWatch Alarms for deployment failures
- X-Ray tracing for distributed tracing
Further Reading
- Reference Documentation - Detailed technical reference for GitHub Actions syntax, OIDC configuration, ECR operations, task definitions, and CloudFormation integration
- Production Examples - Complete, production-ready workflows including basic deployments, multi-environment setups, blue/green deployments, private ECR with scanning, CloudFormation stack updates, and full CI/CD pipelines with testing
Key Concepts
- GitHub Actions: Automate workflows from GitHub repository events
- OIDC Authentication: Secure, tokenless authentication between GitHub and AWS
- ECR: Amazon Elastic Container Registry for Docker image storage
- ECS: Amazon Elastic Container Service for container orchestration
- Fargate: Serverless compute engine for ECS without managing servers
- Task Definition: Blueprint for ECS containers (similar to Pod spec in Kubernetes)
- Service: Long-running ECS service with load balancing and auto-scaling
- CloudFormation: Infrastructure as Code for AWS resource management
- Blue/Green Deployment: Zero-downtime deployment strategy with CodeDeploy
Common Troubleshooting
Authentication failures:
- Verify OIDC trust relationship matches GitHub organization/repository
- Check IAM role has proper permissions for ECR and ECS
- Ensure GitHub Actions repository has
id-token: writepermission
Deployment failures:
- Check CloudWatch Logs for application errors
- Verify task definition matches service requirements
- Ensure sufficient CPU/memory in Fargate cluster
- Review health check configuration
ECR push failures:
- Verify repository exists and permissions are correct
- Check image tag format and registry URL
- Ensure Docker daemon is running in GitHub Actions runner
- Verify image size doesn't exceed ECR limits
CloudFormation rollback:
- Review stack events in AWS Console
- Check parameter values match resource constraints
- Verify IAM role has
cloudformation:UpdateStackpermission - Enable termination protection for production stacks
Related Skills
- aws-cloudformation-ecs - Design and implement ECS cluster architecture
- aws-sdk-java-v2-ecs - Programmatic ECS management with Java SDK
- aws-cloudformation - Core CloudFormation patterns and best practices
Constraints and Warnings
Resource Limits
- GitHub Actions Limits: GitHub Actions has usage limits per account (minutes, storage)
- Workflow File Size: Workflow files cannot exceed 1 MB in size
- Job Matrix Limits: Matrix jobs have limits on total combinations
- Artifact Retention: Artifacts and logs have default 90-day retention
Authentication Constraints
- OIDC Tokens: OIDC tokens have limited lifetime (typically 5 minutes)
- Role Session Duration: IAM role session duration maximum is 12 hours
- Permission Scope: GitHub OIDC role should have least-privilege permissions
- Cross-Account Access: Cross-account deployments require appropriate trust relationships
Operational Constraints
- Deployment Speed: CloudFormation deployments may take time; don't assume instant completion
- Stack Locking: Stacks cannot be updated while another deployment is in progress
- ECR Rate Limits: ECR has API rate limits that may affect large deployments
- ECS Service Limits: ECS has limits on tasks per service and services per cluster
Security Constraints
- Secret Management: Never store secrets in GitHub repository or workflow files
- OIDC Provider: OIDC provider must be configured in AWS account before first use
- Repository Access: Workflow secrets are scoped to repository; organization secrets differ
- Token Security: GitHub tokens should have minimum required permissions (contents: read, id-token: write)
Cost Considerations
- GitHub Actions: Minutes beyond free tier incur costs based on runner type
- ECR Storage: Container images stored in ECR incur monthly storage costs
- ECS/Fargate: Fargate tasks incur costs for vCPU and memory resources
- Data Transfer: Data transfer between GitHub runners and AWS resources incurs costs
Deployment Constraints
- Stack Drift: Manual changes to resources cause stack drift
- Change Set Limits: Multiple change sets in progress can cause confusion
- Rollback Limits: Failed deployments roll back by default; can be disabled
- Timeout Settings: Deployment timeouts should account for application startup time
Additional Files
Source
git clone https://github.com/giuseppe-trisciuoglio/developer-kit/blob/main/plugins/developer-kit-aws/skills/aws-cloudformation/aws-cloudformation-task-ecs-deploy-gh/SKILL.mdView on GitHub Overview
Deploy containerized apps to Amazon ECS using GitHub Actions CI/CD, while managing infrastructure with CloudFormation. This skill covers authentication (OIDC or IAM), building Docker images, pushing to ECR, updating task definitions, and deploying ECS services with production-ready strategies across multiple environments.
How This Skill Works
A GitHub workflow authenticates to AWS (OIDC preferred), builds and pushes Docker images to ECR, renders and updates ECS task definitions, and deploys ECS services. It integrates CloudFormation for infrastructure updates and supports blue/green or rolling deployment strategies, including private ECR repositories with image scanning.
When to Use It
- Deploying Docker containers to Amazon ECS
- Setting up GitHub Actions CI/CD pipelines for AWS
- Configuring AWS authentication for GitHub Actions (OIDC or IAM keys)
- Implementing blue/green or rolling deployments
- Managing CloudFormation stacks from CI/CD
Quick Start
- Step 1: Set up AWS OIDC authentication for GitHub Actions and create the necessary IAM roles
- Step 2: Create an ECR private repository with image scanning enabled and push permissions
- Step 3: Add a GitHub Actions workflow that builds, pushes the image, renders the task definition, and deploys to ECS (via CloudFormation if needed)
Best Practices
- Prefer AWS OIDC authentication for GitHub Actions and grant least-privilege IAM roles
- Enable image scanning on private ECR repositories and tag images with commit SHAs
- Render and update ECS task definitions dynamically in CI to reference new images
- Use blue/green deployment or rolling strategies to minimize downtime
- Synchronize infrastructure with CloudFormation updates and maintain change audibility
Example Use Cases
- Example 1: GitHub Actions workflow that builds a Docker image, logs into ECR, and pushes the image before deploying to ECS
- Example 2: Update ECS Task Definition from CI using aws-actions/amazon-ecs-render-task-definition
- Example 3: Configure AWS credentials in a GitHub Actions workflow to assume a deployment role
- Example 4: Deploy to ECS with a blue/green strategy and track environments across dev/stage/prod
- Example 5: Manage CloudFormation stacks from CI/CD to apply infrastructure changes alongside ECS deployments