A Task Definition is a JSON document that answers one question: "Exactly how should this container run?" Think of it as a recipe card — it lists every ingredient (image, CPU, memory, environment variables, ports) and every instruction (startup command, health check, log destination) needed to produce a running container.
Key Components
Container Image
The source of truth for what code runs. This can be a public image (nginx:latest) or a private image in ECR (123456789.dkr.ecr.us-east-1.amazonaws.com/my-app:v1.4.2). Always pin to a specific tag in production — latest is a reliability anti-pattern because it makes deployments non-deterministic.
CPU and Memory
ECS uses a unit called CPU units where 1024 units = 1 vCPU. You specify resources at two levels:
- Task level: The total ceiling for the entire task (required for Fargate).
- Container level: The allocation per individual container within the task (useful for sidecar patterns).
{
"cpu": "512",
"memory": "1024",
"containerDefinitions": [
{
"name": "api",
"image": "123456789.dkr.ecr.us-east-1.amazonaws.com/my-api:v2.1.0",
"cpu": 512,
"memory": 1024,
"portMappings": [
{ "containerPort": 8080, "protocol": "tcp" }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-api",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
IAM Roles — Two Distinct Roles, Two Distinct Purposes
This is one of the most commonly confused aspects of ECS. There are two separate IAM roles:
- Task Execution Role: Used by the ECS agent (the AWS infrastructure layer) to set up the task. It needs permission to pull the container image from ECR and to write log streams to CloudWatch. Your application code never uses this role.
- Task Role: Used by your application code while it runs. If your API needs to read from S3 or write to DynamoDB, those permissions go here. This is the ECS equivalent of an EC2 instance profile.
Task Execution Role → ECS Agent → Pull image, create log group
Task Role → Your App → Call S3, DynamoDB, SQS
Networking Mode: Always awsvpc
ECS supports several networking modes, but awsvpc is the correct choice for all modern workloads. It gives every running task its own Elastic Network Interface (ENI) with a private IP address from your VPC subnet. This means:
- Each task is addressable like an EC2 instance.
- Security Groups apply at the task level (not the host level).
- No port collision issues between tasks on the same host.
Immutable Revisions
Task Definitions are immutable. You cannot edit one — you create a new Revision (v1, v2, v3...). This is a feature, not a limitation. It means every deployment is traceable, and rolling back is as simple as pointing your Service at a previous revision number. Your entire deployment history is preserved automatically.
Interviewers frequently ask: "What's the difference between the Task Role and the Task Execution Role in ECS?" A weak answer conflates them. The strong answer: "The Task Execution Role is for AWS infrastructure operations — pulling images and writing logs. The Task Role is for your application's AWS API calls. Mixing them up is a security risk because you'd be granting your application unnecessary permissions to manage ECS infrastructure."