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
- Go to
https://aws.amazon.com/
- Sign up for a free tier account (needs credit/debit card
).
- Enable MFA for security
.
- Set region (e.g.,
us-east-1
,ap-south-1
).
- 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:
- AWS Console → Search
ECR
→ Create repository - Configure:
-
Name:
my-app
- Visibility:
Private
- Tag immutability: Enabled
- 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:
- AWS Console → ECS → Create Cluster
- Choose:
-
Networking only
→ Fargate -
EC2 + Networking
→ EC2- Cluster Name:
my-app-cluster
- Proceed → ECS will create VPC and subnets
- Cluster Name:
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:
- ECS → Task Definitions → Create new
- Launch Type: Fargate
- 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:
ECS → Your Cluster → Create Service
Launch Type: Fargate
Choose Task Definition
Desired tasks:
1
or moreAttach Load Balancer:
- ALB → New or existing
- Create Target Group → port
3000
- Health Check path:
/health
- Listener on port
80
→ forward to Target Group
- Enable Auto Scaling (optional)
Step 6: Testing Our Service (
with Node.js Tips!)
Basic Test
- Go to EC2 > Load Balancers → Copy DNS URL
- Visit in browser → You should see your app
- Confirm task is running: ECS > Cluster > Tasks
- 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)
-
Use
.env.production
withdotenv
and pass via Task Definition - Reverse proxy with NGINX (optional for advanced setups)
-
Health Check Endpoint (
/health
): return200 OK
JSON, no DB calls -
Use
pm2
inside container for better process management (optional) -
Avoid console.log in production → Use
winston
orpino
- Enable Structured Logging → Send logs to CloudWatch
- Monitor memory & CPU metrics via CloudWatch
- Enable ECS Exec to debug running container
- Use HTTPS via ACM with Load Balancer
-
Auto-Deploy via GitHub Actions +
AWS CLI
orCodePipeline
- Set container limits (soft/hard memory) to avoid OOM crashes
-
Use Secrets Manager for DB/API credentials
- Test locally with
docker run -p 3000:3000 my-app
before push -
Set
NODE_ENV=production
for optimized performance -
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