Server

ECS Fargate Task Networking

By Prabath Thalangama· October 24, 2026· 3 min read
#aws#ecs#fargate

Introduction

Fargate runs containers without you managing EC2. Networking is always awsvpc mode: each task gets its own elastic network interface (ENI) in your VPC, with its own private IP and security group — like a mini-instance.

The task ENI

  • The task's containers share that ENI (and its localhost).
  • The security group you attach to the task controls its inbound/outbound.
  • The task lands in the subnets you specify in the service's network configuration.
  • awsvpc means container port == host port (there's no port mapping/NAT like bridge mode) — the ALB targets the task IP directly on the container port.

Public vs private subnets

Fargate tasks need outbound internet to pull the image (from ECR or Docker Hub), reach AWS APIs, and send logs — unless you use VPC endpoints.

Placement assignPublicIp Needs
Public subnet ENABLED IGW route; task gets a public IP
Private subnet DISABLED NAT Gateway for egress, or VPC endpoints for ECR/S3/CloudWatch/Secrets Manager

The common production setup: tasks in private subnets, an ALB in public subnets, NAT Gateway (or endpoints) for egress. Public-subnet tasks with assignPublicIp: ENABLED are fine for simple cases but expose the task IP.

"CannotPullContainerError" almost always means: private subnet, no NAT, no ECR/S3 endpoint. ECR needs com.amazonaws.<region>.ecr.api, ecr.dkr, an S3 gateway endpoint (layers live in S3), and com.amazonaws.<region>.logs for CloudWatch.

Task role vs execution role

  • Execution role — used by the ECS agent to pull the image, fetch secrets for the task definition, and write logs. AmazonECSTaskExecutionRolePolicy + secretsmanager:GetSecretValue if you inject secrets.
  • Task role — the credentials your application code uses to call AWS (S3, DynamoDB, SQS). This is the one you scope to least privilege per service.

They're separate. App can't read its S3 bucket? That's the task role. Task won't start / can't pull? Execution role (or networking).

Load balancing

ALB (public subnets)
  └─ target group (target-type: ip)   <- Fargate registers task IPs here
       └─ health check on the container port + path
  └─ ECS service keeps the target group in sync as tasks start/stop

Target type must be ip for Fargate (not instance). The task security group must allow inbound from the ALB's security group on the container port.

Service discovery (service-to-service)

  • ECS Service Connect (newer) — a managed proxy; services reach each other by a short name, with retries and metrics.
  • Cloud Map DNS — the service registers api.internal → task IPs in a private hosted zone.
  • Or just put an internal ALB / NLB in front of each service.

Verification and troubleshooting

aws ecs describe-tasks --cluster c --tasks <id> \
  --query 'tasks[].{last:lastStatus,health:healthStatus,att:attachments}'
aws ecs describe-services --cluster c --services api \
  --query 'services[].events[:5]'
  • CannotPullContainerError / ResourceInitializationError — no egress path. Private subnet without NAT or the ECR/S3/logs VPC endpoints. Add them.
  • Task starts then stops, exit 0/1 — the app crashed; aws logs tail the log group. Or the container command/entrypoint is wrong.
  • ALB target unhealthy — health check path returns non-2xx, wrong port, the task SG doesn't allow the ALB SG, or healthCheckGracePeriodSeconds too short for a slow boot.
  • App gets AccessDenied calling AWS — task role missing the permission (not the execution role).
  • Secrets not injected — execution role lacks secretsmanager:GetSecretValue / kms:Decrypt, or the secret ARN in the task def is wrong.
  • Task can reach the internet but not another internal service — the target service's SG doesn't allow this task's SG, or Cloud Map/Service Connect isn't configured.
  • Intermittent 5xx during deploys — no connection draining / the container doesn't handle SIGTERM; set stopTimeout and drain in-flight requests.
  • Runs in one AZ only — service network config lists one subnet. List one per AZ for spread.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.