CI/CD Automation with GitHub Actions (Modern Alternative)

Introduction
Instead of manually running terraform apply and docker push, this guide sets up automated CI/CD with GitHub Actions. Every time you push to main, your app builds, tests, pushes to ECR, and deploys to ECS Fargate automatically.
What You'll Learn:
✅ Create GitHub Actions workflow for ECS Fargate
✅ Automated Docker build and push to ECR
✅ Auto-update ECS task definition
✅ Environment variables and secrets management
✅ Manual approval for production deployments
✅ Rollback to previous version if tests fail
Prerequisites:
GitHub repository with your app code
1. GitHub Actions Workflow File
Create .github/workflows/deploy.yml:
name: Deploy to ECS Fargate
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
AWS_REGION: ap-south-1
ECR_REPOSITORY: ecs-app-repository
ECS_CLUSTER: ecs-production-cluster
ECS_SERVICE: ecs-app-service
ECS_TASK_DEFINITION: ecs-app-task
CONTAINER_NAME: ecs-app
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
env:
NODE_ENV: test
build-and-push:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
- name: Download task definition
run: |
aws ecs describe-task-definition \
--task-definition ${{ env.ECS_TASK_DEFINITION }} \
--query taskDefinition \
--output json > task-definition.json
- name: Fill in the new image ID in task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}
- name: Deploy to Amazon ECS
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
- name: Verify deployment
run: |
aws ecs describe-services \
--cluster ${{ env.ECS_CLUSTER }} \
--services ${{ env.ECS_SERVICE }} \
--query 'services[0].deployments[0].status'
2. Set Up GitHub Secrets
In GitHub Repository Settings → Secrets:
AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Create IAM User for GitHub:
aws iam create-user --username github-actions-deployer
aws iam create-access-key --user-name github-actions-deployer
# Attach policy
aws iam attach-user-policy \
--user-name github-actions-deployer \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess
3. Manual Approval for Production
Add manual approval gate:
jobs:
deploy-production:
needs: build-and-push
runs-on: ubuntu-latest
environment: production # Requires manual approval
steps:
# ... (same as deploy job)
In GitHub → Settings → Environments → Add "production" → Require reviewers
4. Rollback if Tests Fail
- name: Deploy to Amazon ECS
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
- name: Rollback if deployment failed
if: failure()
run: |
aws ecs update-service \
--cluster ${{ env.ECS_CLUSTER }} \
--service ${{ env.ECS_SERVICE }} \
--force-new-deployment \
--task-definition ${{ env.ECS_TASK_DEFINITION }}:1
Deployment Flow:
Push to main
↓
Run tests (fail → stop)
↓
Build Docker image
↓
Push to ECR (tag: commit SHA)
↓
Update ECS task definition
↓
Deploy to ECS (wait for stability)
↓
Manual approval (if production environment)
↓
Deployment complete
Total Series Cost (All 7 Parts):
| Resource | Monthly Cost |
|---|---|
| ECS Fargate (2 tasks) | $60 |
| ALB | $16 |
| NAT Gateway | $35 |
| RDS PostgreSQL | $15 (free tier) |
| ECR | $0.05 |
| CloudWatch Logs | $5 |
| CodeDeploy | $5 |
| Total | ~$136/month |
Final Summary (Complete Series)
You now have a production-ready AWS ECS Fargate deployment:
✅ Part 1: VPC networking (public/private subnets, security groups)
✅ Part 2: ECR Docker image push
✅ Part 3: ECS Fargate cluster with Terraform
✅ Part 4: Blue-Green zero-downtime deployments
✅ Part 5: CloudWatch monitoring + SNS alerts
✅ Part 6: RDS PostgreSQL database integration
✅ Part 7: GitHub Actions CI/CD automation
This is exactly what companies hire for—put this on your resume/LinkedIn/portfolio!
If this helped you, I'd really appreciate your support. You can buy me a coffee here: buymeacoffee.com/vatul16 ☕
Thanks for reading!
About the author
- Hi, I'm Atul! I am a software engineer with a strong focus on DevOps, Cloud Infrastructure, and automation. I spend my time building scalable CI/CD pipelines, mastering tools like Docker, Terraform, and AWS, and breaking down complex cloud concepts into accessible, hands-on tutorials. I believe the best way to learn is to build, break, and document the process.
Comments
Join the discussionNo comments yet. Be the first to comment.
Zero to Production with AWS ECS Fargate: Terraform, CI/CD, RDS, Monitoring
A hands-on AWS ECS Fargate series that takes a containerized app from zero to production using Terraform, VPC networking, ECR, Application Load Balancer, blue-green deployments, CloudWatch monitoring, RDS PostgreSQL, Secrets Manager, and GitHub Actions CI/CD.





