πŸš€ Deploying a Full-Stack App on AWS with Terraform, ECS, and GitHub Actions – Step-by-Step Guide

Cloud deployments don’t have to be a nightmare of manual steps and unpredictable outcomes.

In this post, I’ll walk you through how I deployed a Dockerized full-stack application (FastAPI + Next.js) on AWS using ECS Fargate, Terraform for IaC, and GitHub Actions for automated CI/CD.

Whether you’re a developer or DevOps enthusiast, this guide will help you confidently move your apps from local to scalable cloud-native infrastructure.


πŸ› οΈ Tech Stack Used

ComponentTool/Service
FrontendNext.js
BackendFastAPI (Python)
ContainerizationDocker
IaCTerraform
CI/CDGitHub Actions
Cloud PlatformAWS ECS Fargate, ALB, CloudWatch
Secrets ManagerAWS Secrets Manager

🧱 1. Dockerizing the Application

Both the frontend and backend apps are containerized using multi-stage Docker builds.

Example: FastAPI Dockerfile

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Next.js was built using the next build command and served via next start.


πŸ™ 2. Setting Up GitHub Actions CI/CD

My GitHub Actions workflow performs:

  • Linting & Testing

  • Docker Build

  • Image Push to AWS ECR

  • Terraform Deployment

Key Features:

  • Automatic deployment on main push

  • Git SHA-based version tagging

  • Reusable secrets from GitHub and AWS


☁️ 3. Infrastructure Provisioning with Terraform

Here’s what Terraform provisions:

  • βœ… VPC, Subnets, Internet Gateway

  • βœ… ECS Cluster & Services (frontend & backend)

  • βœ… ALB & Target Groups with routing rules

  • βœ… IAM Roles and Policies

  • βœ… CloudWatch Logs

  • βœ… S3 backend for remote Terraform state

Example: Terraform ECS Service Snippet

resource "aws_ecs_service" "backend" {
  name            = "backend-service"
  cluster         = aws_ecs_cluster.main.id
  launch_type     = "FARGATE"
  task_definition = aws_ecs_task_definition.backend.arn
  desired_count   = 1

  load_balancer {
    target_group_arn = aws_lb_target_group.backend.arn
    container_name   = "backend"
    container_port   = 8000
  }

  network_configuration {
    subnets         = var.private_subnets
    security_groups = [aws_security_group.ecs.id]
    assign_public_ip = true
  }
}

πŸ”’ 4. Secrets Management

AWS Secrets Manager is used to store API keys and environment variables securely.

IAM roles are attached to ECS Task Definitions to fetch secrets securely without hardcoding them.


πŸ“ˆ 5. Monitoring & Alerts

  • CloudWatch dashboards for ECS service CPU utilization

  • CPU-based alarms trigger email notifications via SNS

  • ALB health checks on /api/health and / routes


πŸ§ͺ 6. Testing and Validation

  • Frontend tested using @testing-library/react

  • Backend tested using pytest + httpx client

  • Health endpoints validated automatically in CI pipeline

  • Verified ALB routes via curl and browser


🧠 Challenges I Faced (And Solved)

  1. ALB 504 Gateway Timeout
    πŸ”§ Fixed by updating security group to allow port 8000 and correcting health check path.

  2. Terraform State Conflicts
    πŸͺ£ Solved using S3 backend with locking enabled via DynamoDB.

  3. Secrets Not Loading in Container
    πŸ” Resolved by updating Task Role permissions and using secrets block in container_definitions.


βœ… Final Result

You now have a fully automated, scalable, and secure deployment pipeline that:

  • Provisions infrastructure via Terraform

  • Pushes Docker images to ECR

  • Deploys to ECS with auto-scaling & load balancing

  • Monitors with alerts and secure secrets


πŸ“Œ Next Steps

If you'd like a post on:

  • πŸ” GitOps and Helm integration

  • πŸ“Š Monitoring with Prometheus + Grafana

  • πŸ’‘ Cost optimization for AWS workloads

Let me know in the comments!


πŸ”– Tags

#devops #terraform #aws #githubactions #docker #ecs #fullstack

0
Subscribe to my newsletter

Read articles from Joel Chandanshiv directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Joel Chandanshiv
Joel Chandanshiv