What Is AWS ECS?
The Gap ECS Fills
You have a Docker image in ECR. How do you actually run it in production?
You could SSH into an EC2 instance and run docker run ... — but then you're back to managing uptime, restarts on crash, and manual deployments. ECS is AWS's answer to "run this container reliably, at scale, with minimal server management."
ECS Launch Types
Fargate (Recommended for Most Cases)
With Fargate, AWS manages the underlying infrastructure completely. You specify CPU and memory requirements, and AWS provisions and manages the machines that run your containers. You never SSH into anything — there are no EC2 instances to patch or monitor.
EC2 Launch Type
With the EC2 launch type, you manage a cluster of EC2 instances. ECS schedules containers onto those instances. More control (specific instance types, GPU support) but more operational overhead.
Start with Fargate unless you have a specific reason not to.
Core Concepts
Cluster
A cluster is a logical grouping of ECS resources — it's the boundary within which your tasks and services run. One cluster can contain multiple services. Think of it as the "namespace" for your application.
Cluster: my-app-production
├── Service: api (3 tasks running)
└── Service: worker (2 tasks running)
Task Definition
A task definition is the blueprint for running a container — equivalent to docker run arguments, stored as a versioned JSON document. It specifies:
{
"family": "my-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "api",
"image": "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app/api:v1.2.0",
"portMappings": [{ "containerPort": 3000 }],
"environment": [
{ "name": "NODE_ENV", "value": "production" }
],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:ssm:us-east-1:123456789012:parameter/my-app/db-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
Key fields:
cpu/memory— Fargate sizes in vCPU units (256 = 0.25 vCPU) and MBimage— the ECR URI (or Docker Hub image)secrets— pull sensitive values from SSM Parameter Store at runtime (never hardcode secrets)logConfiguration— sends container stdout/stderr to CloudWatch Logs automatically
Task
A task is a running instance of a task definition — one or more containers executing together. A task is to ECS what a pod is to Kubernetes.
Service
A service maintains a desired number of running tasks. If a task stops or crashes, the service starts a replacement. Services also integrate with load balancers to distribute traffic.
Service: api
desiredCount: 3 → ECS ensures 3 tasks are always running
loadBalancer: my-alb → ALB routes traffic to healthy tasks
The Full Deployment Flow
1. Build image locally: docker build -t my-app/api .
2. Push to ECR: docker push 123456789012.dkr.ecr.../my-app/api:v1.3.0
3. Update task definition: new revision pointing to :v1.3.0
4. Update ECS service: aws ecs update-service --task-definition my-api:5
5. ECS rolling update: starts new tasks with v1.3.0, drains and stops old ones
6. Load balancer: traffic shifts to new tasks only after health checks pass
This is a zero-downtime deployment — ECS never terminates old tasks until new tasks are healthy and serving traffic.
Secrets Management
Never put secrets in environment variables in the task definition — they'd be visible in the console. Use AWS SSM Parameter Store or Secrets Manager:
# Store the secret
aws ssm put-parameter \
--name "/my-app/database-url" \
--value "postgresql://user:password@host:5432/db" \
--type SecureString
# Reference it in the task definition (ECS injects it at runtime)
"secrets": [{ "name": "DATABASE_URL", "valueFrom": "/my-app/database-url" }]
The ECS task role needs ssm:GetParameters permission to read from SSM.
Load Balancer Integration
Attach an Application Load Balancer (ALB) to your ECS service:
- Create an ALB with a target group (type: IP, protocol: HTTP, port: 3000)
- In the ECS service configuration, select the ALB and target group
- ECS registers/deregisters task IPs with the target group automatically as tasks start and stop
The ALB handles health checks — only healthy tasks receive traffic.