Docker Orchestration with AWS ECS – Full Guide (with Node.js Production Testing & Tips



This content originally appeared on DEV Community and was authored by Darshan Vasani

🚢 Docker Orchestration with AWS ECS – Full Guide (with Node.js Production Testing & Tips)

🧠 What is Docker Orchestration?

Docker Orchestration means managing the lifecycle of containers:

  • 📦 Deploying
  • 🔁 Scaling (up/down)
  • 🚥 Load balancing
  • 🛠 Updating
  • 💥 Handling failures

Popular Orchestration Tools:

  • Docker Swarm 🐝
  • Kubernetes (K8s) ☸
  • Amazon ECS 🚀
  • Amazon EKS (for Kubernetes) ☁

We’ll focus on AWS ECS using Fargate (serverless) and EC2 launch type.

🛠 Step 1: Setting Up AWS Account

  1. Go to 👉 https://aws.amazon.com/
  2. Sign up for a free tier account (needs credit/debit card 💳).
  3. Enable MFA for security 🔐.
  4. Set region (e.g., us-east-1, ap-south-1) 🌍.
  5. Create an IAM user with AdministratorAccess if not using root.

🧴 Step 2: Setting up Amazon ECR (Elastic Container Registry)

ECR is AWS’s private Docker registry.

🪜 Steps:

  1. AWS Console → Search ECR → Create repository 📂
  2. Configure:
  • Name: my-app
  • Visibility: Private 🔒
  • Tag immutability: Enabled ✅
    1. Push Docker Image to ECR:
# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.us-east-1.amazonaws.com

# Build and Tag image
docker build -t my-app .

# Tag with ECR repo URI
docker tag my-app:latest <your-account-id>.dkr.ecr.us-east-1.amazonaws.com/my-app:latest

# Push image
docker push <your-account-id>.dkr.ecr.us-east-1.amazonaws.com/my-app:latest

🧰 Step 3: Setting up ECS Cluster

An ECS Cluster is where your containers run.

🪜 Steps:

  1. AWS Console → ECS → Create Cluster
  2. Choose:
  • Networking onlyFargate
  • EC2 + Networking → EC2
    1. Cluster Name: my-app-cluster
    2. Proceed → ECS will create VPC and subnets 🛰

📝 Step 4: ECS Task Definition Setup

A Task Definition = Docker container blueprint.

👇 Key Components:

  • Task Role (IAM)
  • Docker Image from ECR
  • Port mappings (e.g., 80:3000)
  • CPU & Memory: 256 CPU, 512 MiB RAM
  • Log configuration: AWS CloudWatch
  • Environment variables, secrets 🔐
  • Health checks: /health or /

🪜 Steps:

  1. ECS → Task Definitions → Create new
  2. Launch Type: Fargate
  3. Add container:
  • Name: my-app
  • Image: <ECR Image URL>
  • Port: 3000
  • Logging: awslogs, with group: /ecs/my-app

⚖ Step 5: ECS Service Setup with Load Balancer

The Service handles:

  • Keeping tasks running
  • Restarting failed containers
  • Auto-scaling

🪜 Steps:

  1. ECS → Your Cluster → Create Service

  2. Launch Type: Fargate

  3. Choose Task Definition

  4. Desired tasks: 1 or more

  5. Attach Load Balancer:

  • ALB → New or existing
  • Create Target Group → port 3000
  • Health Check path: /health
  • Listener on port 80 → forward to Target Group
  1. Enable Auto Scaling (optional)

🧪 Step 6: Testing Our Service (💥 with Node.js Tips!)

✅ Basic Test

  1. Go to EC2 > Load Balancers → Copy DNS URL 🌐
  2. Visit in browser → You should see your app 🚀
  3. Confirm task is running: ECS > Cluster > Tasks
  4. Logs: CloudWatch > /ecs/my-app 📜

✅ Deep Testing (For Node.js Applications)

🔹 1. Check container logs:

aws logs get-log-events \
  --log-group-name "/ecs/my-app" \
  --log-stream-name "<your-log-stream>"

Or via CloudWatch Console.

🔹 2. CURL/HTTP test:

curl http://<load-balancer-dns>/health

✅ Ensure response is 200 OK. If not, ECS will kill and restart your task.

🔹 3. Test environment variables:

Add this in your Node.js app:

console.log('ENV:', process.env.NODE_ENV);

Set "NODE_ENV": "production" in Task Definition.

🔹 4. Debug failing deployments:

Check:

  • Task status (Stopped?)
  • View Reason (StoppedReason)
  • Logs (CloudWatch)
  • Health Check (endpoint must return 2xx)

🔹 5. Enable ECS Exec:

Run shell commands inside the running container:

aws ecs execute-command \
  --cluster my-app-cluster \
  --task <task-id> \
  --container my-app \
  --interactive \
  --command "/bin/sh"

Requires enabling ECS Exec & permissions.

🧹 Step 7: Clean up Resources (🧽 Avoid Charges!)

✅ Checklist:

  • Stop ECS Service
  • Delete Tasks
  • Delete Load Balancer
  • Delete Target Groups
  • Delete ECR Repository (optional)
  • Delete Cluster
  • Delete VPC (if created)
  • Delete CloudWatch logs
aws ecr delete-repository --repository-name my-app --force

⚙ Manual vs Automatic Orchestration

Feature Manual Automatic
Deploy new container 🚀 CLI or Console CI/CD + ECS Service Updates
Scale app 🔄 You change task count Auto Scaling based on CPU/Memory/Requests
Monitor and Heal 🩺 Manual restart ECS restarts crashed tasks
Load Balancing 🌐 Manually configure ELB ECS auto-registers tasks to Target Groups
Image Updates 🔄 Push new tag and update task def Use CodePipeline / GitHub Actions + Blue/Green

✅ Real-World Production Tips (💡 Especially for Node.js)

  1. Use .env.production with dotenv and pass via Task Definition
  2. Reverse proxy with NGINX (optional for advanced setups)
  3. Health Check Endpoint (/health): return 200 OK JSON, no DB calls
  4. Use pm2 inside container for better process management (optional)
  5. Avoid console.log in production → Use winston or pino
  6. Enable Structured Logging → Send logs to CloudWatch
  7. Monitor memory & CPU metrics via CloudWatch
  8. Enable ECS Exec to debug running container
  9. Use HTTPS via ACM with Load Balancer
  10. Auto-Deploy via GitHub Actions + AWS CLI or CodePipeline
  11. Set container limits (soft/hard memory) to avoid OOM crashes
  12. Use Secrets Manager for DB/API credentials 🔐
  13. Test locally with docker run -p 3000:3000 my-app before push
  14. Set NODE_ENV=production for optimized performance
  15. Use a lightweight base image like node:18-alpine

🧾 Summary Cheatsheet

Step Task Tool/Service
1⃣ Create AWS Account AWS Console
2⃣ Push Image to ECR ECR, Docker CLI
3⃣ Setup ECS Cluster ECS
4⃣ Define Task Definition ECS
5⃣ Create Service + Load Balancer ECS + ALB
6⃣ Test Your Application Load Balancer URL
7⃣ Cleanup Console / CLI


This content originally appeared on DEV Community and was authored by Darshan Vasani