AWS for DevOps — Containers Practice Exercises
7.6 — Containers Practice Exercises
Test your understanding of ECS, ECR, task definitions, services, and ALB integration.
Exercise 1 — Fargate vs EC2
A team is evaluating launch types for these workloads. Recommend Fargate or EC2 for each:
| # | Workload |
|---|---|
| A | A web API with variable traffic (5-500 requests/sec) |
| B | A machine learning inference service that needs GPU |
| C | A startup’s development environment (3 microservices) |
| D | A company running 200 containers 24/7 with predictable load |
Show Answer
| # | Recommendation | Why |
|---|---|---|
| A | Fargate | Per-task scaling is perfect for variable traffic; no servers to manage |
| B | EC2 | Fargate doesn’t support GPUs; need GPU instances (p3, g4dn) |
| C | Fargate (or Fargate Spot) | Simplicity matters for small teams; Spot saves money in dev |
| D | EC2 with Reserved Instances | At scale with predictable load, EC2 Reserved is significantly cheaper than Fargate |
Exercise 2 — Fix the Task Definition
This task definition fails to register with the error: “Invalid CPU or memory value”. Why?
{
"family": "my-app",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "4096",
"containerDefinitions": [
{
"name": "app",
"image": "123456789012.dkr.ecr.ap-south-1.amazonaws.com/my-app:v1",
"essential": true,
"portMappings": [{ "containerPort": 8080 }]
}
]
}
Show Answer
Problem: Invalid CPU/memory combination.
cpu=256 (0.25 vCPU) only supports memory values of 512, 1024, or 2048 (0.5, 1, or 2 GB). memory=4096 (4 GB) is not a valid option for 0.25 vCPU.
Fix: Either:
- Increase CPU:
"cpu": "512"(0.5 vCPU supports up to 4 GB) - Or decrease memory:
"memory": "2048"(2 GB fits with 0.25 vCPU)
Always check the Fargate CPU/memory combination table before registering task definitions.
Exercise 3 — IAM Role Confusion
A developer’s ECS task can pull its image from ECR and write logs to CloudWatch, but the application code inside the container gets AccessDenied when trying to read from an S3 bucket. The execution role has s3:GetObject permission. What is wrong?
Show Answer
Problem: The S3 permission is on the Execution Role instead of the Task Role.
- Execution Role = permissions for the ECS agent (pull images, write logs, read secrets)
- Task Role = permissions for your application code (S3, DynamoDB, SQS, etc.)
The ECS agent doesn’t use S3 for your business logic — your app code does. Move the s3:GetObject permission to the Task Role (taskRoleArn in the task definition).
Key rule: If your application code needs to call an AWS service, add the permission to the Task Role. If the ECS infrastructure needs it (images, logs, secrets), add it to the Execution Role.
Exercise 4 — ECR Lifecycle Design
A team pushes 5-10 Docker images per day to ECR. After 6 months, they have 1,200 images and their ECR storage costs are growing. Design a lifecycle policy that:
- Keeps the last 20 tagged images (tags like
v1.0.1,v1.0.2) - Removes untagged images older than 3 days
- Keeps all images tagged with
release-*indefinitely
Show Answer
{
"rules": [
{
"rulePriority": 1,
"description": "Keep all release images forever",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["release-"],
"countType": "imageCountMoreThan",
"countNumber": 9999
},
"action": { "type": "expire" }
},
{
"rulePriority": 2,
"description": "Keep only last 20 version-tagged images",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["v"],
"countType": "imageCountMoreThan",
"countNumber": 20
},
"action": { "type": "expire" }
},
{
"rulePriority": 3,
"description": "Remove untagged images after 3 days",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 3
},
"action": { "type": "expire" }
}
]
}
Key points:
- Rules are evaluated in priority order — lower number = higher priority
- Rule 1 (priority 1) protects
release-*images by setting an unreachable threshold - Rule 2 keeps only the most recent 20
v*images - Rule 3 cleans up dangling untagged images quickly
Exercise 5 — ECS + ALB Architecture
Design the architecture for a microservices application with these requirements:
- Two services:
api(REST API) andweb(frontend) - Single ALB with path-based routing:
/api/*→ api service,/*→ web service - Both services on Fargate in private subnets
- Auto-scaling: API scales on request count, Web scales on CPU
List the AWS resources needed and the key configuration for each.
Show Answer
Resources needed:
- VPC with 2 public subnets (ALB) + 2 private subnets (tasks)
- NAT Gateway in public subnet (tasks need internet for ECR pulls)
- ALB in public subnets, internet-facing
- Two Target Groups:
api-tg: target-type=ip, port=8080, health-check=/api/healthweb-tg: target-type=ip, port=3000, health-check=/health
- Listener on port 80 (or 443 with ACM certificate):
- Rule priority 10: path-pattern
/api/*→api-tg - Default action →
web-tg
- Rule priority 10: path-pattern
- ECS Cluster:
production - Two Task Definitions:
api:1— cpu=512, memory=1024, port=8080web:1— cpu=256, memory=512, port=3000
- Two ECS Services:
api— desired=3, load-balancer=api-tg, health-check-grace=120sweb— desired=2, load-balancer=web-tg, health-check-grace=60s
- Two ECR Repositories:
api,web - Security Groups:
sg-alb: inbound 80/443 from 0.0.0.0sg-api-tasks: inbound 8080 from sg-alb onlysg-web-tasks: inbound 3000 from sg-alb only
- Auto-scaling:
- API: TargetTrackingScaling with
ALBRequestCountPerTarget, target=500 - Web: TargetTrackingScaling with
ECSServiceAverageCPUUtilization, target=70%
- API: TargetTrackingScaling with
- IAM Roles: Execution role (ECR + Logs), Task roles (one per service)
Next Chapter → Infrastructure as Code