# ECS, Fargate and ECR

## 1. The Pieces

- **ECR (Elastic Container Registry)** — private Docker/OCI image registry: repositories, image scanning, lifecycle policies, cross-account/region replication, immutable tags.
- **ECS (Elastic Container Service)** — AWS's container orchestrator: runs and keeps containers running, integrates with ALB, IAM, CloudWatch, Secrets Manager, Service Connect.
- **Fargate** — serverless compute for containers: you specify vCPU/memory per task; AWS runs it on infrastructure you never see. The alternative is the **EC2 launch type** (you manage an Auto Scaling group of container instances).

```
ECR repo ──image──► task definition (blueprint) ──► ECS service (keeps N tasks running)
                                                     └─ tasks on Fargate in private subnets ─► ALB target group
```

## 2. Task Definitions

A **task definition** is a versioned JSON blueprint (family + revision):

| Field | Meaning |
|---|---|
| `cpu` / `memory` | task size (Fargate combinations, e.g. 0.25 vCPU/0.5 GB … 16 vCPU/120 GB) |
| `containerDefinitions[]` | image, port mappings, environment, **secrets** (`valueFrom` Secrets Manager/SSM), log configuration, health check, `essential` |
| `networkMode: awsvpc` | each task gets its own ENI and private IP (required for Fargate) — security groups apply per task |
| `executionRoleArn` | used by the ECS agent to **pull the image, push logs, fetch secrets** |
| `taskRoleArn` | assumed by **your application code** (S3, DynamoDB, SQS access) |
| `runtimePlatform` | `ARM64` (Graviton, cheaper) or `X86_64` |

Sidecars (log routers like FireLens/Fluent Bit, OpenTelemetry collectors, Envoy) are additional containers in the same task, sharing its network namespace (`localhost`).

## 3. Services

An **ECS service** maintains `desiredCount` tasks of a task definition, replaces unhealthy ones, registers them with load balancer target groups, and performs deployments:

- **Rolling update** (default): `minimumHealthyPercent` / `maximumPercent` control how many tasks are replaced at once; the **deployment circuit breaker** stops and rolls back a deployment whose tasks keep failing.
- **Blue/green** with CodeDeploy: a second target group, traffic shifting (canary/linear), automatic rollback on alarms (`devops-cloud/cicd/02-deployment_strategies`).
- **Service auto scaling** (Application Auto Scaling): target tracking on CPU, memory, or `ALBRequestCountPerTarget`; step scaling; scheduled (`11-scalability_and_monitoring/`).
- **Service Connect / Cloud Map** for service-to-service discovery by name (`system-design/system-design/08-service_discovery`).
- **Capacity providers**: Fargate, **Fargate Spot** (up to ~70% cheaper, can be interrupted with a 2-minute warning — good for workers), or EC2 Auto Scaling groups.

## 4. ECR in Practice

```bash
aws ecr create-repository --repository-name petpal/api \
  --image-tag-mutability IMMUTABLE --image-scanning-configuration scanOnPush=true
aws ecr get-login-password | docker login --username AWS --password-stdin 111111111111.dkr.ecr.eu-west-1.amazonaws.com
docker build -t 111111111111.dkr.ecr.eu-west-1.amazonaws.com/petpal/api:${GIT_SHA} .
docker push 111111111111.dkr.ecr.eu-west-1.amazonaws.com/petpal/api:${GIT_SHA}
```

- **Immutable tags** + tagging by commit SHA: a tag always means the same image; deploy by tag or digest, never `latest`.
- **Lifecycle policies**: keep the last N images per prefix, expire untagged images after a few days.
- **Scanning**: basic (on push) or enhanced (Amazon Inspector, continuous) — `devops-cloud/docker/07-container_security`.
- Private subnets without NAT need **VPC endpoints** for `ecr.api`, `ecr.dkr`, S3 (layers), CloudWatch Logs and Secrets Manager (`10-internet_gateway_and_nat_gateway/`).

## 5. ECS vs EKS vs Lambda

| | ECS on Fargate | EKS (`16-eks/`) | Lambda (`12-…`) |
|---|---|---|---|
| unit | task (containers) | pod | function |
| control plane cost | free | ~$73/month per cluster | none |
| learning curve | low, AWS-native | high (Kubernetes) | lowest |
| portability | AWS-only | portable Kubernetes APIs | AWS-only |
| long-running / steady load | ✅ | ✅ | ❌ (15 min max, per-request pricing) |
| ecosystem | AWS integrations | huge (Helm, operators, service meshes) | serverless ecosystem |

ECS on Fargate is the pragmatic default for AWS-only teams running containers; EKS when you need Kubernetes portability or its ecosystem.

## Under the Hood: How a Fargate Task Starts

When a service needs a new task, the ECS scheduler picks a subnet (spreading across AZs) and asks Fargate for capacity matching the requested CPU/memory and architecture. Fargate places the task on a host it manages and starts a dedicated **microVM** (Firecracker-based isolation, one task per VM boundary), creates and attaches an **ENI** in your subnet with your security groups, then the agent — using the **execution role** — authenticates to ECR, pulls image layers (from the regional cache, through S3), fetches secrets, configures the log driver, and starts containers in dependency order. Once containers pass health checks, ECS registers the task's IP in the target group; the ALB starts sending traffic after the target passes the load balancer's health checks. Large images and cold layer caches dominate start time — keep images small (multi-stage builds) and consider **SOCI** lazy loading for very large images.

![An image pushed to ECR with an immutable SHA tag is referenced by a task definition with execution and task roles; the ECS service keeps tasks running on Fargate in private subnets with their own ENIs, registers them with the ALB, rolls deployments with a circuit breaker and scales with application auto scaling](diagrams/01-ecs-fargate.svg)

## Common Pitfalls

1. **One role for everything** — merge execution and task roles and over-grant.
2. **`latest` tags / mutable tags** — you can't tell what's running or roll back reliably.
3. **Secrets as plain environment variables** in the task definition.
4. **Tasks in public subnets with public IPs** "to reach ECR" instead of NAT/endpoints.
5. **No circuit breaker** — a broken image loops forever.
6. **No ECR lifecycle policy** — storage costs grow unbounded.

## Quick Reference

```
ECR: immutable tags (git SHA) · scan on push · lifecycle policy · VPC endpoints for private pulls
task def: cpu/memory · awsvpc · execution role (pull/logs/secrets) vs task role (app) · secrets valueFrom · logs
service: desired count · rolling + circuit breaker or CodeDeploy blue/green · autoscaling · Service Connect
capacity: Fargate / Fargate Spot / EC2 · ECS default for AWS-only containers, EKS for Kubernetes
