Deploying to AWS

Author

Date Published

Reading Time

3 min

1. The Image Repository: Amazon ECR

Before you can run a container, AWS needs a place to store your compiled Docker images. You will use Amazon Elastic Container Registry (ECR).

Repository Isolation: Create a separate ECR repository for each service (e.g., asaas-frontend and asaas-backend).

Immutable Versioning: Enforce immutable tags. Your CI/CD pipeline should tag images with the specific Git Commit SHA (e.g., asaas-frontend:a1b2c3d) rather than overriding a latest tag. This ensures instant, reliable rollbacks if a deployment fails.

Security Scanning: Enable "Basic Scanning" on push. ECR will automatically scan your node:20-alpine base layers for CVE vulnerabilities before the container ever reaches production.

2. The Compute Engine: AWS Fargate

Fargate is a serverless compute engine. You do not provision, patch, or maintain EC2 instances. You define the exact CPU and memory your container needs, and AWS provisions the compute capacity dynamically.

Task Definitions: This is the AWS equivalent of your local docker-compose.yml. You create a JSON configuration that tells ECS which ECR image to pull, how much RAM/CPU to allocate (e.g., 1 vCPU, 2GB RAM), and which ports to expose (e.g., Port 3000).

Secrets Management: Never hardcode .env variables in the Task Definition. Use AWS Secrets Manager to inject your MongoDB URI and Payload CMS secret keys securely into the container at runtime.

3. Orchestration & Traffic Routing: ECS and ALB

To make your application accessible to the public internet securely, you combine an ECS Service with an Application Load Balancer (ALB).

Application Load Balancer (ALB): The ALB sits in your public subnets and listens for HTTP/HTTPS traffic. It holds your SSL/TLS certificates (managed freely via AWS Certificate Manager) and terminates the secure connection.

Target Groups: The ALB routes traffic to a Target Group. Because Fargate IP addresses change dynamically as containers scale, the Target Group automatically tracks the internal IPs of your active containers.

The ECS Service: This connects your Task Definition to the ALB. It guarantees that a specific number of containers (Tasks) are always running. If a Next.js container crashes, the ECS Service automatically detects the failure, drains it from the Load Balancer, and spins up a fresh replacement.

4. Auto-Scaling Rules

One of the primary reasons to move to AWS is elasticity. You configure your ECS Service to scale automatically based on demand.

CPU/Memory Tracking: Set a target utilization, such as 70% CPU. If traffic to Siraj Academy spikes, ECS automatically provisions additional Fargate tasks to handle the load, and the ALB immediately begins routing traffic to the new instances.

Scale Down: When traffic subsides, AWS kills the unneeded containers, meaning you only pay for the exact compute time your application consumed.

5. Automated CI/CD Pipeline (GitHub Actions)

Your deployment process must be entirely hands-off. When a Pull Request is merged into the main branch, GitHub Actions orchestrates the release.

OIDC Authentication: GitHub securely authenticates with AWS using OpenID Connect (no long-lived IAM keys required).

Build & Push: GitHub runs docker build, utilizing the optimized multi-stage Dockerfiles, and pushes the image to ECR.

Update Task Definition: The pipeline creates a new revision of the ECS Task Definition pointing to the new Git SHA image tag.

Rolling Deployment: GitHub triggers an aws ecs update-service command. ECS spins up the new containers, waits for the ALB health checks to return a 200 OK, routes traffic to the new version, and then gracefully shuts down the old containers. This results in zero-downtime deployments.

AWS ECS & ALB Fargate Integration Tutorial

This visual walkthrough demonstrates how to properly configure Target Groups and connect your Application Load Balancer to a Fargate task to ensure dynamic IP addresses are routed correctly.