ECS & Fargate Basics
Six short examples that take you from an empty account to a running Fargate task and back down again: create a cluster, register a task definition, run a task, inspect it, and stop it.
Busca en todas las páginas de la documentación
Six short examples that take you from an empty account to a running Fargate task and back down again: create a cluster, register a task definition, run a task, inspect it, and stop it.
Each example shows the same operation in both Python (boto3) and TypeScript (AWS SDK for JavaScript v3), so the mechanics translate one to one.
pip install boto3 (boto3 1.43.x, Python 3.10+). TypeScript: npm install @aws-sdk/client-ecs (Node.js 18+).aws configure, environment variables, or an IAM role with ecs:* on your test resources.ecsTaskExecutionRole) so it can pull images and write logs.CreateCluster makes a logical grouping for your tasks and services. On Fargate it stays empty of instances - there is nothing to provision.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
resp = ecs.create_cluster(clusterName="demo")
print(resp["cluster"]["clusterArn"])// --- TypeScript (AWS SDK v3) ---
import { ECSClient, CreateClusterCommand } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
const resp = await ecs.send(new CreateClusterCommand({ clusterName: "demo" }));
console.log(resp.cluster?.clusterArn);CreateCluster is effectively idempotent for a name that already exists in ACTIVE state.clusterName, ECS uses a cluster literally named default.RegisterTaskDefinition stores a versioned blueprint. For Fargate you must set the compatibility, awsvpc network mode, and task-level CPU and memory.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
resp = ecs.register_task_definition(
family="web",
requiresCompatibilities=["FARGATE"],
networkMode="awsvpc",
cpu="256", # .25 vCPU, as a string
memory="512", # MiB, as a string
executionRoleArn="arn:aws:iam::111122223333:role/ecsTaskExecutionRole",
containerDefinitions=[{
"name": "web",
"image": "public.ecr.aws/nginx/nginx:latest",
"essential": True,
"portMappings": [{"containerPort": 80, "protocol": "tcp"}],
}],
)
print(resp["taskDefinition"]["taskDefinitionArn"]) # ...:task-definition/web:1// --- TypeScript (AWS SDK v3) ---
import { ECSClient, RegisterTaskDefinitionCommand } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
const resp = await ecs.send(new RegisterTaskDefinitionCommand({
family: "web",
requiresCompatibilities: ["FARGATE"],
networkMode: "awsvpc",
cpu: "256", // .25 vCPU, as a string
memory: "512", // MiB, as a string
executionRoleArn: "arn:aws:iam::111122223333:role/ecsTaskExecutionRole",
containerDefinitions: [{
name: "web",
image: "public.ecr.aws/nginx/nginx:latest",
essential: true,
portMappings: [{ containerPort: 80, protocol: "tcp" }],
}],
}));
console.log(resp.taskDefinition?.taskDefinitionArn); // ...:task-definition/web:1family plus an auto-incrementing revision (web:1, web:2, ...) identifies the definition.cpu and memory are strings and must be a valid Fargate pair (256 CPU allows 512, 1024, or 2048 memory).RunTask with launchType: FARGATE launches the definition. Fargate requires a networkConfiguration naming subnets and security groups.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
resp = ecs.run_task(
cluster="demo",
taskDefinition="web", # latest ACTIVE revision
launchType="FARGATE",
count=1,
networkConfiguration={
"awsvpcConfiguration": {
"subnets": ["subnet-0abc123"],
"securityGroups": ["sg-0abc123"],
"assignPublicIp": "ENABLED",
}
},
)
task_arn = resp["tasks"][0]["taskArn"]
print(task_arn)// --- TypeScript (AWS SDK v3) ---
import { ECSClient, RunTaskCommand } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
const resp = await ecs.send(new RunTaskCommand({
cluster: "demo",
taskDefinition: "web", // latest ACTIVE revision
launchType: "FARGATE",
count: 1,
networkConfiguration: {
awsvpcConfiguration: {
subnets: ["subnet-0abc123"],
securityGroups: ["sg-0abc123"],
assignPublicIp: "ENABLED",
},
},
}));
const taskArn = resp.tasks?.[0].taskArn;
console.log(taskArn);launchType: FARGATE and a networkConfiguration are both mandatory for Fargate.assignPublicIp: ENABLED in a public subnet lets the task pull its image without a NAT gateway.taskDefinition without a revision uses the latest ACTIVE one.resp["failures"] - a task can fail to place even when the call succeeds.ListTasks returns task ARNs; DescribeTasks expands them into full objects with status and container detail.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
arns = ecs.list_tasks(cluster="demo")["taskArns"]
if arns:
desc = ecs.describe_tasks(cluster="demo", tasks=arns)
for t in desc["tasks"]:
print(t["taskArn"], t["lastStatus"], t["desiredStatus"])// --- TypeScript (AWS SDK v3) ---
import { ECSClient, ListTasksCommand, DescribeTasksCommand } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
const { taskArns } = await ecs.send(new ListTasksCommand({ cluster: "demo" }));
if (taskArns && taskArns.length) {
const desc = await ecs.send(new DescribeTasksCommand({ cluster: "demo", tasks: taskArns }));
for (const t of desc.tasks ?? []) {
console.log(t.taskArn, t.lastStatus, t.desiredStatus);
}
}ListTasks returns only ARNs; you always follow up with DescribeTasks for detail.DescribeTasks accepts up to 100 task ARNs per call.lastStatus moves through PROVISIONING, PENDING, RUNNING, STOPPED; compare it against desiredStatus.ListTasks with desiredStatus or serviceName to scope large clusters.Instead of polling, use the built-in tasks_running waiter to block until the task reaches RUNNING.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
ecs.get_waiter("tasks_running").wait(cluster="demo", tasks=[task_arn])
print("task is running")// --- TypeScript (AWS SDK v3) ---
import { ECSClient, waitUntilTasksRunning } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
await waitUntilTasksRunning(
{ client: ecs, maxWaitTime: 300 },
{ cluster: "demo", tasks: [taskArn!] },
);
console.log("task is running");DescribeTasks for you until the target status or a timeout.tasks_running fails fast if a task goes STOPPED before it reaches RUNNING.waitUntilTasksStopped for teardown flows.maxWaitTime; Fargate provisioning can take tens of seconds.StopTask ends a running task; DeleteCluster removes the (empty) cluster when you are finished.
# --- Python (boto3) ---
import boto3
ecs = boto3.client("ecs", region_name="us-east-1")
ecs.stop_task(cluster="demo", task=task_arn, reason="demo cleanup")
ecs.get_waiter("tasks_stopped").wait(cluster="demo", tasks=[task_arn])
ecs.delete_cluster(cluster="demo")// --- TypeScript (AWS SDK v3) ---
import { ECSClient, StopTaskCommand, waitUntilTasksStopped, DeleteClusterCommand } from "@aws-sdk/client-ecs";
const ecs = new ECSClient({ region: "us-east-1" });
await ecs.send(new StopTaskCommand({ cluster: "demo", task: taskArn!, reason: "demo cleanup" }));
await waitUntilTasksStopped({ client: ecs, maxWaitTime: 300 }, { cluster: "demo", tasks: [taskArn!] });
await ecs.send(new DeleteClusterCommand({ cluster: "demo" }));StopTask sends SIGTERM, waits the stop timeout, then SIGKILL; it is a graceful stop.reason string surfaces in DescribeTasks and CloudTrail, so make it meaningful.DeleteCluster fails if the cluster still has active services or running tasks.Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 23 jul 2026