Deploy Container To Aws

Deploy Container To Aws

Reading time1 min
#Cloud#AWS#Containers#ECS#Fargate

Efficient Container Deployment to AWS: ECS + Fargate

Many teams bog down deployments by maintaining EC2-based clusters, wrestling with patching cycles and scaling headaches. In practice, ECS with Fargate offloads this entire class of problem—no EC2 fleet, just containers as an isolated, managed service.

Problem: How to Ship Containers Without Infrastructure Overhead

High-velocity software teams need rapid deployment, horizontal scaling, and zero interest in managing OS lifecycles. ECS + Fargate targets this with a serverless container runtime—provision once, scale automatically, limit blast radius at the task level.

Below: a proven ECS/Fargate pipeline, used in production, minimizes manual steps and infrastructure sprawl. No hand-edited launch scripts, no SSH into hosts.


Container Image: Build and Push to ECR

Non-negotiable: Docker images must reside in a registry accessible to ECS. Amazon ECR (Elastic Container Registry) supports fine-grained IAM policies and lifecycle rules—important if you iterate quickly.

Workflow: Bash (tested with AWS CLI v2, Docker 20.10+)

# 1. Create an ECR repo. Change region as needed.
aws ecr create-repository --repository-name my-app --region us-east-1

# 2. Log in to ECR (token expires in 12 hours)
aws ecr get-login-password --region us-east-1 \
  | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com

# 3. Build and tag your image
docker build --platform linux/amd64 -t my-app:2024-06-10 .
docker tag my-app:2024-06-10 <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/my-app:2024-06-10

# 4. Push
docker push <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/my-app:2024-06-10

Note: Tag with a date or Git SHA for traceability. “latest” is not recommended in CI systems.

Known issue: Insufficient IAM permissions for ECR will fail authentication—error:
denied: User is not authorized to perform: ecr:BatchCheckLayerAvailability


Cluster: ECS Logical Group

No EC2, but you still declare a cluster for logical grouping and isolation (metrics, scaling).

aws ecs create-cluster --cluster-name my-fargate-cluster

Nothing to patch, nothing to monitor from a compute perspective. Cluster merely groups task deployments.


Task Definition: JSON Spec for Workload

Task definitions are the crux—specify image, resource requests, network mode, environment variables. Fargate mandates networkMode: awsvpc (each task gets its own ENI).

Minimal task definition (ECS Fargate):

{
  "family": "my-app-task",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [{
    "name": "my-app-container",
    "image": "<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/my-app:2024-06-10",
    "portMappings": [{
      "containerPort": 8080,
      "protocol": "tcp"
    }],
    "environment": [
      {"name": "APP_ENV", "value": "production"}
    ],
    "essential": true
  }]
}
aws ecs register-task-definition --cli-input-json file://task-definition.json

Gotcha: For Fargate, possible CPU/memory values are fixed combinations, e.g., cpu: 256memory: 512 or 1024.


Service: Running the Workload

Want durable, self-healing deployments? Use ECS Services. Update the task definition, and ECS handles rolling upgrades.

aws ecs create-service \
  --cluster my-fargate-cluster \
  --service-name my-app-service \
  --task-definition my-app-task \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration 'awsvpcConfiguration={subnets=["subnet-abc123"],securityGroups=["sg-123456"],assignPublicIp="ENABLED"}'
  • Subnets: private for internal APIs, public with assignPublicIp="ENABLED" for external endpoints.
  • Security Groups: open port 8080 (or your app port) for inbound traffic.

Side note: ECS will not auto-create subnets or security groups; ensure these exist first.


Verification

Check ECS Service status in AWS Console, or via CLI:

aws ecs list-tasks --cluster my-fargate-cluster --service-name my-app-service

Each running task gets an ENI and IP. Hit the public IP on the container port:

curl http://<task-ip>:8080/

Look for status 200/OK—real payload should appear.
If you get “Connection refused”: double-check security group ingress and port mappings.


Operational Enhancements

ALB Integration

For production, attach an Application Load Balancer (ALB) to the ECS Service.
Benefits: health checks, sticky sessions, SSL termination, path-based routing.

Example mapping:

ALB ListenerTarget GroupECS Task
HTTPS:443app-tg-80808080/tcp

Enable deregistration delay for zero-downtime deploys.
ECS Console > Service > Load balancing > Add listener rule.

Autoscaling

Managed via ECS Service Auto Scaling policies.
Scale number of tasks based on:

  • Average CPU utilization (e.g., >60% for 5 min)
  • Memory percent
  • Custom CloudWatch Alarm

CLI Example:

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

Side effect: Too-aggressive scaling policies can exhaust subnet IPs—plan CIDR accordingly.


Key Learnings & Trade-offs (Mid-Flow)

  • No SSH. Debugging uses ECS Exec (since late 2022), but requires additional IAM/config.
  • Cold starts: Fargate spins up in ~30 seconds, but infrequent workloads may see multi-second latency.
  • Decoupling build and deploy pipelines tightens control. Pin images with digests to avoid breaking production on re-tag.

Alternatives like AWS Copilot or CDK can synthesize CloudFormation for ECS, but direct CLI and JSON gives the deepest visibility.


Summary Table

StepCLI Command (sample)Config Artifact
Push Docker image to ECRdocker push ...Dockerfile
Create ECS clusteraws ecs create-cluster ...-
Register Fargate taskaws ecs register-task-definition ...task-definition.json
Create ECS Serviceaws ecs create-service ...-
Attach ALB, add scalingECS Console / CLI(optional)

Unobvious tip: To minimize downtime during deployments, configure your ECS Service’s deployment type as “blue/green” (CodeDeploy integration), not just “rolling update”. This is often overlooked in quick-start guides.

Future direction: Infrastructure as Code (e.g., Terraform aws_ecs_* resources) further shrinks manual error surface.

Not covered: Custom VPC, advanced network policies, ECS Exec troubleshooting.

Deployment can be seamless, but the edge cases—enforcing least-privilege IAM, managing service limits, avoiding CIDR exhaustion—require ongoing attention.


Questions or need a skeleton Terraform/ECS config? This can be integrated with most CI/CD pipelines—Jenkins, GitHub Actions, CodePipeline.