Best Practices
Practical guidelines for secure, reliable, and cost-effective ECS in production.
A checklist to keep production ECS healthy:
Security
- Use separate task roles (app permissions) and execution roles (pull images, write logs).
- Keep secrets in Secrets Manager or SSM, never in plain env vars.
- Run tasks in private subnets with least-privilege security groups.
Reliability
- Spread tasks across multiple Availability Zones.
- Define health checks and set sensible deployment percentages.
- Enable Container Insights and alarms.
Cost
- Right-size CPU and memory; use Fargate Spot or EC2 for savings.
- Scale down non-production environments when idle.
Example
{
"family": "web",
"taskRoleArn": "arn:aws:iam::123456789012:role/webAppRole",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "512",
"memory": "1024",
"containerDefinitions": [
{
"name": "web",
"image": "web:9",
"essential": true,
"portMappings": [
{
"containerPort": 80
}
]
}
]
}When to use it
- A security team mandates that all ECS task definitions use non-root users and read-only root file systems to reduce the blast radius of a container compromise.
- A FinOps team tags every ECS service and task definition with cost-center tags so spend is attributed correctly in AWS Cost Explorer.
- A reliability team enables the deployment circuit breaker on every ECS service so bad deployments automatically roll back instead of requiring manual intervention.
More examples
Run Container as Non-Root User
Runs the container as UID 1000 with a read-only root filesystem, mounting a writable /tmp volume so the app cannot modify the container image layer.
{
"name": "api",
"image": "my-api:latest",
"user": "1000:1000",
"readonlyRootFilesystem": true,
"mountPoints": [
{"sourceVolume": "tmp", "containerPath": "/tmp"}
]
}Enable Circuit Breaker on All Services
Iterates over every service in the cluster and enables the deployment circuit breaker with automatic rollback on each one.
for SVC in $(aws ecs list-services --cluster prod --query 'serviceArns[]' --output text); do
aws ecs update-service \
--cluster prod \
--service "$SVC" \
--deployment-configuration \
'deploymentCircuitBreaker={enable=true,rollback=true}'
donePropagate Tags to Tasks
Enables ECS-managed tag propagation so all cost-allocation tags applied to the service are automatically copied to every task it launches.
aws ecs update-service \
--cluster prod \
--service api \
--enable-ecs-managed-tags \
--propagate-tags SERVICE \
--tags key=Team,value=platform key=CostCenter,value=engineering
Discussion