Docs
/
AWS Cloud
Chapter 12

12 — ECS & Fargate

What is ECS?

Elastic Container Service — run Docker containers on AWS. Two launch types:

EC2 Launch TypeFargate Launch Type
You manageEC2 instances (cluster)Nothing (serverless)
Scaling infraYou scale instancesAWS auto-scales
CostCheaper at scalePay per vCPU/memory/second
ControlFull OS accessNo OS access
Best forCost-sensitive, GPU, large workloadsSimplicity, variable workloads

Architecture

┌─ ECS Cluster ──────────────────────────────┐
│                                             │
│  ┌─ Service: api (desired: 3) ──────────┐  │
│  │  ┌──────┐  ┌──────┐  ┌──────┐       │  │
│  │  │Task 1│  │Task 2│  │Task 3│       │  │
│  │  │(api) │  │(api) │  │(api) │       │  │
│  │  └──────┘  └──────┘  └──────┘       │  │
│  └──────────────────────────────────────┘  │
│                                             │
│  ┌─ Service: worker (desired: 2) ───────┐  │
│  │  ┌──────┐  ┌──────┐                  │  │
│  │  │Task 1│  │Task 2│                  │  │
│  │  └──────┘  └──────┘                  │  │
│  └──────────────────────────────────────┘  │
└─────────────────────────────────────────────┘

ALB → Service (api) → Tasks → Containers
ConceptDescription
ClusterLogical grouping of services/tasks
Task DefinitionBlueprint (like docker-compose for one service)
TaskRunning instance of a task definition (one or more containers)
ServiceMaintains desired count of tasks, integrates with ALB

Task Definition

{
  "family": "api",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::123:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123:role/ecsTaskRole",
  "containerDefinitions": [
    {
      "name": "api",
      "image": "123456.dkr.ecr.us-east-1.amazonaws.com/my-app:1.0.0",
      "portMappings": [
        { "containerPort": 3000, "protocol": "tcp" }
      ],
      "environment": [
        { "name": "NODE_ENV", "value": "production" }
      ],
      "secrets": [
        {
          "name": "DATABASE_URL",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123:secret:db-url"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/api",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ]
}

Roles

RolePurpose
Execution RoleECS agent pulls images (ECR), writes logs (CloudWatch), reads secrets
Task RoleYour application accesses AWS services (S3, DynamoDB, SQS)

Service + ALB

aws ecs create-service \
  --cluster my-cluster \
  --service-name api \
  --task-definition api:1 \
  --desired-count 3 \
  --launch-type FARGATE \
  --network-configuration \
    "awsvpcConfiguration={subnets=[subnet-a,subnet-b],securityGroups=[sg-xxx],assignPublicIp=DISABLED}" \
  --load-balancers \
    "targetGroupArn=arn:aws:...target-group/api,containerName=api,containerPort=3000"

Auto Scaling

# Target tracking: scale based on CPU
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/my-cluster/api \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 \
  --max-capacity 20

aws application-autoscaling put-scaling-policy \
  --policy-name cpu-scaling \
  --service-namespace ecs \
  --resource-id service/my-cluster/api \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
    "TargetValue=70,PredefinedMetricSpecification={PredefinedMetricType=ECSServiceAverageCPUUtilization}"

CI/CD Pipeline

Code push → Build image → Push to ECR → Update ECS service

1. CodeBuild builds Docker image
2. Push to ECR with git SHA tag
3. Update task definition with new image
4. ECS performs rolling update (zero downtime)

ECS vs Lambda vs EKS

LambdaECS FargateEKS
Max runtime15 minUnlimitedUnlimited
Container supportNo (OCI images)YesYes
ScalingInstant (ms)MinutesMinutes
ComplexityLowestMediumHighest
Cost (low traffic)CheapestMediumExpensive
Cost (high traffic)ExpensiveCheaperCheapest
Use caseEvent-driven, APIsWeb apps, microservicesComplex orchestration

Key Takeaways

  • Fargate = serverless containers — no instances to manage
  • Task definition = container blueprint; Service = keeps N tasks running
  • Use Execution Role for ECS operations, Task Role for app AWS access
  • Use Secrets Manager for credentials (not environment variables)
  • ALB + ECS Service for load-balanced, auto-scaling web apps
  • Choose Lambda for event-driven, ECS for long-running services, EKS for complex K8s workloads