← Back to DevBytes

ECS: Complete Setup and Configuration Guide

What is Amazon ECS?

Amazon Elastic Container Service (ECS) is a fully managed container orchestration service that allows you to run and scale containerized applications on AWS. It handles the heavy lifting of scheduling containers across a cluster of virtual machines, managing their lifecycle, and integrating deeply with other AWS services like networking, storage, monitoring, and security.

ECS operates using two main launch types:

Core ECS concepts include:

Why ECS Matters

πŸš€ Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

ECS solves the operational complexity of container deployment at scale. It matters for modern development because:

Setting Up ECS: Prerequisites

Before creating your ECS resources, ensure you have:

Step-by-Step Configuration Guide

1. Create an ECS Cluster

A cluster is a namespace for your tasks and services. For a Fargate-only cluster (no EC2 instances), creation is trivial:

aws ecs create-cluster \
  --cluster-name my-fargate-cluster \
  --capacity-providers FARGATE \
  --default-capacity-provider-strategy capacityProvider=FARGATE,weight=1

If you plan to use EC2 launch type, you need to create the cluster and then register EC2 instances with the container agent. For simplicity, the rest of this guide assumes Fargate, but the concepts translate directly to EC2.

2. Define a Task Definition

Create a file named task-definition.json with a complete container specification. Below is a production-ready example running a simple web application:

{
  "family": "my-web-app",
  "networkMode": "awsvpc",
  "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::123456789012:role/myAppTaskRole",
  "cpu": "256",
  "memory": "512",
  "requiresCompatibilities": ["FARGATE"],
  "containerDefinitions": [
    {
      "name": "web-container",
      "image": "public.ecr.aws/mycompany/webapp:latest",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 8080,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "ENVIRONMENT",
          "value": "production"
        },
        {
          "name": "DB_HOST",
          "value": "rds-prod.cluster-cxjxxxxx.us-east-1.rds.amazonaws.com"
        }
      ],
      "secrets": [
        {
          "name": "DB_PASSWORD",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/dbpassword-AbCdEf"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "ecs/webapp-logs",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "web"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ]
}

Key details in this definition:

3. Register the Task Definition

Upload the JSON to ECS. This creates a revision (e.g., my-web-app:1):

aws ecs register-task-definition \
  --cli-input-json file://task-definition.json

Every registration increments the revision number. Services can then reference a specific revision or use the family alone to pick the latest active revision.

4. Create a Service

Now you can create a service that maintains a desired number of tasks, optionally behind a load balancer. The following command creates a service with Fargate networking, public IP assignment (for internet access), and associates it with an Application Load Balancer target group:

aws ecs create-service \
  --cluster my-fargate-cluster \
  --service-name webapp-service \
  --task-definition my-web-app:1 \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=["subnet-abc123","subnet-def456"],securityGroups=["sg-xyz789"],assignPublicIp=ENABLED}" \
  --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/webapp-tg/abcd1234,containerName=web-container,containerPort=8080" \
  --deployment-configuration "maximumPercent=200,minimumHealthyPercent=100" \
  --enable-execute-command

Breakdown of important parameters:

5. Configure Load Balancing (Optional)

For production workloads, a load balancer distributes traffic and enables zero-downtime deployments. Here's how to set up an Application Load Balancer and target group, then link them to the ECS service:

First, create the target group:

aws elbv2 create-target-group \
  --name webapp-tg \
  --protocol HTTP \
  --port 8080 \
  --target-type ip \
  --vpc-id vpc-xxxxxxxx

Note: target-type ip is mandatory for Fargate tasks because they get IP addresses directly, not instance-based targets.

Create the Application Load Balancer (requires at least two public subnets):

aws elbv2 create-load-balancer \
  --name webapp-alb \
  --type application \
  --subnets subnet-public1 subnet-public2 \
  --security-groups sg-alb-public

Create a listener that forwards to the target group:

aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/webapp-alb/1234567890abcdef \
  --protocol HTTP \
  --port 80 \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/webapp-tg/abcd1234

After the service is created with the load-balancers parameter, ECS automatically registers and deregisters task IPs with the target group as tasks start and stop.

6. Set Up Auto Scaling

ECS service auto scaling uses Application Auto Scaling. You can scale based on CPU, memory, or custom CloudWatch metrics. The following registers the service as a scalable target and attaches a CPU-based scaling policy:

# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/my-fargate-cluster/webapp-service \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 \
  --max-capacity 10

# Create scaling policy (CPU target tracking)
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/my-fargate-cluster/webapp-service \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name cpu-target-tracking \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration file://scaling-policy.json

Example content of scaling-policy.json:

{
  "TargetValue": 70.0,
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
  },
  "ScaleOutCooldown": 120,
  "ScaleInCooldown": 120
}

This will keep average CPU around 70%, adding or removing tasks as needed. Similar policies exist for memory and request counts per target (ALBRequestCountPerTarget).

7. Logging and Monitoring

In the task definition we specified awslogs as the log driver. Before using it, the CloudWatch log group must exist:

aws logs create-log-group --log-group-name ecs/webapp-logs

Ensure the execution role has permissions like:

{
  "Effect": "Allow",
  "Action": [
    "logs:CreateLogStream",
    "logs:PutLogEvents"
  ],
  "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:ecs/webapp-logs:*"
}

Monitor ECS service events, task state changes, and CloudWatch alarms. Enable Container Insights for advanced metrics (CPU, memory per task, network) by opting in through the console or CLI:

aws ecs update-cluster-settings \
  --cluster my-fargate-cluster \
  --settings name=containerInsights,value=enabled

Best Practices

Conclusion

Amazon ECS abstracts the complexity of container orchestration, letting you focus on your application code while AWS handles scheduling, scaling, and infrastructure. Through Fargate, you gain a serverless container platform that requires zero host management and integrates natively with a rich ecosystem of AWS services. By following the configuration steps outlinedβ€”creating a cluster, defining a secure task definition, registering it, running a service with load balancing, enabling auto scaling, and wiring in loggingβ€”you establish a production-grade container environment. Adhering to best practices around security, versioning, monitoring, and infrastructure as code ensures your container workloads remain resilient, cost-efficient, and easy to evolve. With this complete setup, you are ready to deploy, scale, and maintain containerized applications on ECS with confidence.

πŸš€ Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started β€” $23.99/mo
← Back to all articles