ECS Staging Setup Guide
Complete step-by-step guide to set up your FishingLog API staging environment on AWS ECS.
📋 Overview
This guide sets up staging infrastructure:
- ✅ ECR Repository (Docker image storage)
- ✅ RDS PostgreSQL (database)
- ✅ ElastiCache Valkey (caching - optional)
- ✅ Application Load Balancer (traffic distribution)
- ✅ Cloudflare (DNS, SSL, CDN - free!)
- ✅ S3 Bucket (images/media)
- ✅ Security Groups (firewall rules)
- ✅ IAM Roles (permissions)
- ✅ ECS Cluster (container orchestration)
- ✅ CloudWatch (monitoring & logs)
Endpoint: api-staging.reelog.app
🎯 Architecture
Users → Cloudflare (DNS/SSL/CDN) → Load Balancer → ECS Containers → RDS PostgreSQL
↓ ↓
S3 (Images) Valkey (Cache)
📦 Prerequisites
- ✅ AWS Account (console access)
- ✅ Docker installed (for building/pushing images)
- ✅ Domain registered (
reelog.app) - ✅ AWS Cognito User Pool (
us-east-2_TZtGx1T3X) - ✅ ECS Service-Linked Role (
AWSServiceRoleForECS)
Region: us-east-2 (Ohio) - Keep everything in same region
🏷️ Standard Tags
Apply these tags to all resources:
Environment=StagingProject=ReelogPurpose= Resource type (e.g.,LoadBalancer,Database,Cache)Name= Resource name (e.g.,reelog-lb-staging)
🚀 Step 1: Create ECR Repository
- ECR Console → Repositories → Create repository
- Settings:
- Visibility: Private
- Name:
reelog-api-staging - Tag immutability: Enabled
- Image scanning: Leave unchecked (deprecated)
- Encryption: Default (AWS managed)
- Create repository
- Copy Repository URI:
606532921651.dkr.ecr.us-east-2.amazonaws.com/reelog-api-staging
Tags:
Environment=StagingProject=ReelogPurpose=ECRName=reelog-api-staging
🗄️ Step 2: Create RDS PostgreSQL Database
- RDS Console → Databases → Create database
Configuration:
- Creation method: Easy create
- Engine: PostgreSQL (not Aurora)
- Version: PostgreSQL 16.x
- Template: Free tier
- DB instance identifier:
reelog-db-staging - Master username:
fishinglog_admin - Master password: Auto-generate or set your own (⚠️ SAVE IT!)
- DB instance class:
db.t3.micro(Free tier) - Storage: 20 GB (Free tier)
- VPC:
vpc-0e0ba14210312bf06 - Public access: Yes (for staging)
- VPC security group: Create new
reelog-db-sg-staging - Deletion protection: Disabled (for staging)
After creation (5-10 minutes):
- Copy Endpoint:
reelog-db-staging.xxxxx.us-east-2.rds.amazonaws.com - Create database (if not created):
Then:
psql -h reelog-db-staging.xxxxx.us-east-2.rds.amazonaws.com \
-U fishinglog_admin \
-d postgresCREATE DATABASE fishinglog_db;
Tags:
Environment=StagingProject=ReelogPurpose=DatabaseName=reelog-db-staging
🔴 Step 3: Create ElastiCache Valkey Cache (Optional)
Skip for now if you want to get API running first.
- ElastiCache Console → Valkey caches → Create Valkey cache
Configuration:
- Deployment option: Node-based cluster (for free tier)
- Creation method: Easy create
- Configuration: Demo (cache.t4g.micro - free tier eligible)
- Name:
reelog-valkey-staging - Network type: IPv4
- Subnet group: Create new
reelog-valkey-subnet-staging- VPC:
vpc-0e0ba14210312bf06 - Subnets: Select 3 subnets (different AZs)
- VPC:
- Security group: Will update after creation
After creation (5-10 minutes):
- Copy Primary endpoint:
reelog-valkey-staging.xxxxx.cache.amazonaws.com:6379- ⚠️ Use Primary endpoint (not Configuration endpoint) for single-node setup
Update Security Group:
- EC2 Console → Security Groups → Find Valkey security group
- Copy to new security group:
reelog-valkey-sg-staging - Edit inbound rules:
- Remove "All traffic" rule
- Add: Port 6379, Source:
reelog-api-sg-stagingsecurity group
- Outbound: Leave default (all traffic)
- Update Valkey cache to use new security group
Tags:
Environment=StagingProject=ReelogPurpose=CacheName=reelog-valkey-staging
🔒 Step 4: Create Security Groups
Order matters - create in this order:
4.1 Load Balancer Security Group
- EC2 Console → Security Groups → Create security group
- Name:
reelog-lb-sg-staging - Description:
Security group for Application Load Balancer - Staging - VPC:
vpc-0e0ba14210312bf06 - Inbound rules:
- HTTP (80) from
0.0.0.0/0 - HTTPS (443) from
0.0.0.0/0
- HTTP (80) from
- Outbound: Default (all traffic)
- Tags: Environment=Staging, Project=Reelog, Purpose=LoadBalancer, Name=reelog-lb-sg-staging
4.2 API Security Group
- Create security group
- Name:
reelog-api-sg-staging - Description:
Security group for ECS API containers - Staging - VPC:
vpc-0e0ba14210312bf06 - Inbound rules:
- HTTP (80) from
reelog-lb-sg-stagingsecurity group - HTTPS (443) from
reelog-lb-sg-stagingsecurity group
- HTTP (80) from
- Outbound: Default (all traffic)
- Tags: Environment=Staging, Project=Reelog, Purpose=API, Name=reelog-api-sg-staging
Save Security Group ID: sg-08d7ea63ef8d6091e (you'll need this)
4.3 Database Security Group
- Create security group
- Name:
reelog-db-sg-staging - Description:
Security group for RDS database - Staging - VPC:
vpc-0e0ba14210312bf06 - Inbound rules:
- PostgreSQL (5432) from
reelog-api-sg-stagingsecurity group
- PostgreSQL (5432) from
- Outbound: Default (all traffic)
- Tags: Environment=Staging, Project=Reelog, Purpose=Database, Name=reelog-db-sg-staging
⚖️ Step 5: Create Application Load Balancer
5.1 Create Target Group
- EC2 Console → Target Groups → Create target group
- Configuration:
- Target type: IP addresses
- Name:
reelog-api-tg-staging - Protocol: HTTP
- Port: 80
- IP address type: IPv4
- VPC:
vpc-0e0ba14210312bf06 - Protocol version: HTTP1
- Health check: HTTP, Path:
/health, Success codes: 200- Uses
/healthendpoint which doesn't require authentication (for load balancer health checks) - The
/pingendpoint requires authentication and is for authenticated API health checks
- Uses
- Advanced: Healthy threshold: 2, Unhealthy: 3, Interval: 30s
- Tags: Environment=Staging, Project=Reelog, Purpose=TargetGroup, Name=reelog-api-tg-staging
- Create target group
5.2 Request ACM Certificate
- Certificate Manager (ACM) → Request certificate
- Certificate type: Public certificate
- Domain:
api-staging.reelog.app - Validation: DNS validation
- Request
- Copy DNS validation record (Name and Value)
- Add to Cloudflare DNS (Step 13.1) - DNS only (gray cloud)
- Wait 5-10 minutes for validation → Status: "Issued"
5.3 Create Load Balancer
- EC2 Console → Load Balancers → Create Load Balancer
- Type: Application Load Balancer
- Name:
reelog-lb-staging - Scheme: Internet-facing
- IP address type: IPv4
- Network mapping:
- VPC:
vpc-0e0ba14210312bf06 - Subnets: Select at least 2 AZs
- VPC:
- Security groups:
reelog-lb-sg-staging
Listeners:
HTTP (Port 80):
- Action: Redirect to HTTPS (301)
HTTPS (Port 443):
- Action: Forward to
reelog-api-tg-staging - SSL certificate: From ACM →
api-staging.reelog.app - Pre-routing: No pre-routing action
- Target group:
reelog-api-tg-staging, Weight: 1 - Stickiness: Off
- Listener tags: Environment=Staging, Project=Reelog, Protocol=HTTPS, Port=443
Load Balancer tags:
- Environment=Staging, Project=Reelog, Purpose=LoadBalancer, Name=reelog-lb-staging
After creation:
- Copy DNS name:
reelog-lb-staging-809655828.us-east-2.elb.amazonaws.com
🏗️ Step 6: Create ECS Cluster
⚠️ Prerequisite: Check ECS Service-Linked Role
- IAM Console → Roles → Search
AWSServiceRoleForECS - If NOT found, create it:
- IAM → Roles → Create role
- Trusted entity: AWS service → Elastic Container Service
- Select: Elastic Container Service (service-linked role)
- Create role
6.1 Create Cluster
- ECS Console → Clusters → Create cluster
- Configuration:
- Name:
reelog-staging - Service Connect: Leave blank
- Infrastructure: Fargate only
- Container Insights: Turned off (for staging)
- ECS Exec: None
- Encryption: Default AWS managed keys
- Name:
- Tags: Environment=Staging, Project=Reelog, Purpose=ECSCluster, Name=reelog-staging
- Create
🔐 Step 7: Create IAM Roles
7.1 Task Execution Role
- IAM Console → Roles → Create role
- Trusted entity type: Select AWS service
- Use case: Select Elastic Container Service
- You'll see: "Allow an AWS service like EC2, Lambda, or others to perform actions in this account"
- Scroll down to find "Elastic Container Service"
- Select: Elastic Container Service Task
- This is the specific use case for ECS tasks
- Click "Next"
- Add permissions:
- Search and select:
AmazonECSTaskExecutionRolePolicy - Search and select:
AmazonEC2ContainerRegistryReadOnly
- Search and select:
- Click "Next"
- Role name:
reelog-ecs-task-execution-role - Description:
Execution role for ECS tasks - allows ECR access and CloudWatch logging - Tags (optional but recommended):
- Tag 1: Key=
Environment, Value=Staging - Tag 2: Key=
Project, Value=Reelog - Tag 3: Key=
Purpose, Value=TaskExecutionRole - Tag 4: Key=
Name, Value=reelog-ecs-task-execution-role
- Tag 1: Key=
- Click "Create role"
- After creation, click on the role → Add permissions → Create inline policy:
- JSON tab → Paste:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-2:*:*"
}]
}- Policy name:
CloudWatchLogsPolicy - Create policy
7.2 Task Role
- IAM Console → Roles → Create role
- Trusted entity type: Select AWS service
- Use case: Select Elastic Container Service
- Select: Elastic Container Service Task
- Click "Next"
- Add permissions:
- Search and select:
AmazonS3FullAccess - Or create custom policy for specific bucket access (more secure)
- Search and select:
- Click "Next"
- Role name:
reelog-ecs-task-role - Description:
Task role for ECS containers - allows S3 access - Tags (optional but recommended):
- Tag 1: Key=
Environment, Value=Staging - Tag 2: Key=
Project, Value=Reelog - Tag 3: Key=
Purpose, Value=TaskRole - Tag 4: Key=
Name, Value=reelog-ecs-task-role
- Tag 1: Key=
- Click "Create role"
📦 Step 8: Create ECS Task Definition
- ECS Console → Task Definitions → Create new task definition
- Task definition family:
reelog-api-staging- Family name groups different revisions of the same task definition
- Must be 1-255 characters, valid: a-z, A-Z, 0-9, hyphens (-), underscores (_)
- Launch type: Fargate
- Task size: 0.5 vCPU, 1 GB memory
- Task execution role:
reelog-ecs-task-execution-role - Task role:
reelog-ecs-task-role - Network mode: awsvpc
Container:
- Name:
reelog-api - Image URI:
606532921651.dkr.ecr.us-east-2.amazonaws.com/reelog-api-staging:latest - Port mappings: 80 (HTTP)
- Environment variables:
ASPNETCORE_ENVIRONMENT=StagingASPNETCORE_URLS=http://+:80- ⚠️ CRITICAL: Makes the app listen on port 80 (required for load balancer)
- Without this, ASP.NET Core defaults to port 8080 in containers
ConnectionStrings__DefaultConnection=Host=reelog-db-staging.cn0muq2ok0qq.us-east-2.rds.amazonaws.com;Port=5432;Database=fishinglog_db;Username=fishinglog_admin;Password=YOUR_PASSWORDRedis__ConnectionString=reelog-valkey-staging.oe3wvy.cache.amazonaws.com:6379(if using Valkey)
- Logging: awslogs
- Log driver: awslogs
- Log group:
/ecs/reelog-api-staging - Region:
us-east-2 - Stream prefix:
ecs - awslogs-create-group: ✅ Keep enabled (recommended)
- Automatically creates CloudWatch log group if it doesn't exist
- Safety net - even though we created it manually in Step 11
- Harmless if log group already exists
- Prevents errors if log group is accidentally deleted
Tags (optional but recommended):
- Tag 1: Key=
Environment, Value=Staging - Tag 2: Key=
Project, Value=Reelog - Tag 3: Key=
Purpose, Value=TaskDefinition - Tag 4: Key=
Name, Value=reelog-api-staging
Create
🚀 Step 9: Create ECS Service
- ECS Console → Clusters →
reelog-staging→ Services → Create - Configuration:
- Task definition:
reelog-api-staging:1 - Service name:
reelog-api-staging
- Task definition:
Compute configuration - advanced:
Compute options:
- Select: Launch type ✅ RECOMMENDED
- ✅ Simpler - Direct launch without capacity provider strategy
- ✅ Standard approach - Works well for most use cases
- ✅ Easier to manage - No need to configure capacity providers
Launch type:
- Select: Fargate
- Serverless containers - no EC2 instances to manage
- Auto-scaling handled by AWS
Alternative: Capacity provider strategy (Advanced - Not needed):
- ⚠️ Use custom - Only if you need advanced task distribution
- ⚠️ More complex - Requires configuring capacity providers
- ⚠️ Use cluster default - Only if cluster has default capacity provider strategy configured
- ✅ For staging, use Launch type - Simpler and sufficient
Troubleshooting configuration - recommended:
Turn on ECS Exec:
- Enable ECS Exec: ✅ Enable (recommended for staging)
- ✅ Useful for debugging - Run interactive commands in containers
- ✅ Helpful for troubleshooting - Inspect container state, check logs, test connections
- ✅ Safe for staging - Can help diagnose issues quickly
What is ECS Exec?
- Allows you to run interactive commands in running containers
- Similar to
docker execbut for ECS containers - Useful for debugging, checking environment variables, testing database connections
- Requires task role with appropriate permissions (already configured)
When to use:
- ✅ Staging: Enable - Useful for debugging and troubleshooting
- ⚠️ Production: Consider enabling for troubleshooting, but be mindful of security
- Use cases: Check logs, test database connections, inspect environment variables, debug issues
Note: ECS Exec can only be enabled when launching new tasks, not for existing ones. If you need it later, you'll need to update the service.
Continue with:
- Number of tasks: 2
- VPC:
vpc-0e0ba14210312bf06 - Subnets: Select at least 2 subnets
- Security groups:
reelog-api-sg-staging - Load balancer: Application Load Balancer
- Load balancer: Select
reelog-lb-staging - Listener: Select HTTPS:443 (or HTTP:80 if you only have HTTP listener)
- Select the HTTPS listener (port 443) since we configured HTTPS in Step 5.3
- This is the listener that forwards traffic to your target group
- Target group: Select
reelog-api-tg-staging - Container to load balance:
- Container name:
reelog-api - Container port:
80 - Production listener port:
443(matches the HTTPS listener) - Or it may show as:
reelog-api:80:443
- Container name:
- Load balancer: Select
- Service auto scaling - optional: ✅ Enable (recommended)
- VPC:
Auto Scaling Configuration:
Use service auto scaling:
- ✅ Check "Use service auto scaling" to enable automatic scaling
Task limits:
- Minimum number of tasks:
2- Lower boundary - service will never scale below this
- Ensures high availability (at least 2 tasks)
- Maximum number of tasks:
10- Upper boundary - service will never scale above this
- Prevents runaway costs
Scaling policy type:
- Select: Target tracking ✅ RECOMMENDED
- ✅ Simpler - Automatically adjusts based on target metric value
- ✅ Recommended - AWS manages scaling decisions
- ✅ Works well for most applications
Alternative: Step scaling (Advanced - Not needed):
- ⚠️ More complex - Requires configuring step adjustments and alarms
- ⚠️ More control - Fine-grained scaling based on alarm breaches
- ⚠️ Use only if you need custom scaling behavior
Target tracking policy configuration:
Policy name:
- Name:
cpu-memory-scaling(or leave default)- Identifies this scaling policy
ECS service metric:
- Select: ECSServiceAverageCPUUtilization (for CPU-based scaling)
- ✅ Recommended - Scales based on CPU usage
- Or select ECSServiceAverageMemoryUtilization for memory-based scaling
Target value:
- CPU target:
70(percent)- Service will scale to maintain ~70% CPU utilization
- If CPU > 70%, scale out (add tasks)
- If CPU < 70%, scale in (remove tasks)
Scale-out cooldown period:
- Value:
60seconds (default)- Wait 60 seconds after scaling out before scaling again
- Prevents rapid scaling up
Scale-in cooldown period:
- Value:
300seconds (5 minutes) - recommended- Wait 5 minutes after scaling in before scaling again
- Longer cooldown prevents rapid scaling down
- Gives time to verify traffic decrease is sustained
Turn off scale-in:
- ❌ Leave unchecked (allow scale-in)
- ✅ Recommended - Allows service to scale down when not needed
- ✅ Cost-effective - Saves money when traffic is low
- ⚠️ Check only if you want to prevent scale-in (always keep max tasks)
Optional: Add second scaling policy (Memory):
- Click "Add another policy" (if available)
- Policy name:
memory-scaling - Metric: ECSServiceAverageMemoryUtilization
- Target value:
80(percent) - Same cooldown periods as CPU policy
Note: You can configure multiple scaling policies (CPU and Memory). The service will scale based on whichever metric requires more tasks.
Tags - optional:
Turn on Amazon ECS managed tags:
- ✅ Enable (recommended)
- ✅ Automatically tags tasks with cluster and service names
- ✅ Helps identify tasks in AWS Cost and Usage Report
- ✅ Useful for cost tracking - See costs per service/cluster
- ✅ No downside - Free and helpful
Propagate tags from:
- Select: Task definition ✅ RECOMMENDED
- ✅ Automatically propagates tags from task definition to tasks
- ✅ Consistent tagging - Tasks inherit task definition tags
- ✅ Less manual work - Don't need to tag tasks separately
- Alternative: Service - Propagates service tags to tasks
- Alternative: Do not propagate - No automatic tag propagation
Service tags:
- Click "Add tag" and add each of these:
-
Tag 1:
- Key:
Environment - Value:
Staging
- Key:
-
Tag 2:
- Key:
Project - Value:
Reelog
- Key:
-
Tag 3:
- Key:
Purpose - Value:
ECSService
- Key:
-
Tag 4:
- Key:
Name - Value:
reelog-api-staging
- Key:
-
Tag 5 (Optional):
- Key:
ManagedBy - Value:
Manual
- Key:
What happens:
- Service tags: Applied to the service itself
- ECS managed tags: Automatically added to tasks (cluster name, service name)
- Propagated tags: Task definition tags automatically copied to tasks
- Result: Tasks have comprehensive tags for cost tracking and organization
Create service
🪣 Step 10: Create S3 Bucket
Single bucket with prefixes (recommended for social media apps):
- ✅ One bucket for all content types (users, posts, groups, logs, models)
- ✅ Organize with prefixes (folders) in your application code
- ✅ Simpler management - Single bucket policy, one set of permissions
- ✅ Cost-effective - No per-bucket charges
Bucket Setup:
- S3 Console → Create bucket
- Bucket type: Select General purpose ✅ RECOMMENDED
- ✅ Multi-AZ redundancy - Data stored across multiple Availability Zones
- ✅ Cost-effective - Standard S3 pricing
- ✅ Works with Cloudflare CDN - CDN handles latency
- ✅ Supports all storage classes - Standard, IA, Glacier, etc.
- ✅ Standard choice for most applications
- ⚠️ Directory (Express One Zone) - Only for ultra-low latency needs (not needed here)
- Name:
reelog-content-staging(globally unique)- Generic name allows all content types (images, videos, models, etc.)
- Region:
us-east-2 - Block public access: ✅ Keep all settings enabled (we'll configure this after creation)
- During creation, leave Block Public Access settings ON
- We'll configure public read access AFTER bucket creation
- Versioning: Enable (optional, recommended for staging)
- Encryption: SSE-S3
Tags - optional:
- Click "Add tag" and add each of these:
-
Tag 1:
- Key:
Environment - Value:
Staging
- Key:
-
Tag 2:
- Key:
Project - Value:
Reelog
- Key:
-
Tag 3:
- Key:
Purpose - Value:
Storage
- Key:
-
Tag 4:
- Key:
Name - Value:
reelog-content-staging
- Key:
-
Tag 5 (Optional):
- Key:
ManagedBy - Value:
Manual
- Key:
-
Create bucket
Configure Block Public Access (required before adding bucket policy):
- After bucket creation, go to your bucket → Permissions tab
- Block Public Access settings → Edit
- Uncheck the following setting:
- ✅ Uncheck: "Block public access to buckets and objects granted through new public bucket or access point policies"
- This allows the bucket policy to grant public read access
- Other settings can remain checked for security
- ✅ Uncheck: "Block public access to buckets and objects granted through new public bucket or access point policies"
- Save changes
- Confirm by typing
confirmin the confirmation dialog
Why this is needed:
- The bucket policy grants public read access (
"Principal": "*") - Block Public Access settings prevent public access by default
- We need to allow public bucket policies to enable public read
- This is safe because the policy only allows
GetObject(read), not write/delete
Add Bucket Policy (for public read):
- Still in Permissions tab → Bucket policy → Edit
- Paste the following JSON policy:
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::reelog-content-staging/*"
}]
}
- Save changes
- Verify - You should see a warning that the bucket is publicly accessible (this is expected)
What this policy does:
- Allows public read access (
s3:GetObject) to all objects in the bucket - Anyone can view/download files via URL
- Does NOT allow write, delete, or list operations
- Safe for serving images/media via Cloudflare CDN
Prefix Structure (organized in application code):
reelog-content-staging/
├── users/{userId}/ # User avatars, cover photos, profile photos
├── posts/{postId}/ # Post images/videos
├── groups/{groupId}/ # Group avatars, cover photos
├── logs/{logId}/ # Fishing log photos, catch photos
├── models/ # 3D models (boats, rods, reels)
│ ├── boats/
│ ├── rods/
│ └── reels/
└── temp/ # Temporary uploads (presigned URLs)
Note: Prefix organization happens in your application code when uploading files. The bucket itself is just a container - AWS doesn't enforce folder structure.
📊 Step 11: Create/Update CloudWatch Log Group
Check if log group already exists:
- CloudWatch Console → Logs → Log groups
- Search for
/ecs/reelog-api-staging
If log group exists (update retention):
- Click on
/ecs/reelog-api-staging - Configuration tab → Edit retention
- Retention period: Select 7 days (or your preferred retention)
- Current: 1 week (matches recommendation)
- Save changes
If log group doesn't exist (create new):
- Log groups → Create log group
- Log group name:
/ecs/reelog-api-staging - Retention: 7 days
- Create
Note: AWS may automatically create log groups when ECS tasks start logging. If it already exists, just update the retention settings.
🌐 Step 12: Configure Cloudflare DNS
12.1 ACM Certificate Validation
- ACM Console → Certificate → Copy DNS validation record
- Cloudflare → DNS → Add record
- Type: CNAME
- Name: Validation record name from ACM
- Target: Validation record value from ACM
- Proxy: ❌ DNS only (gray cloud) - Required!
- TTL: Auto
- Comment (optional):
ACM Certificate Validation - api-staging.reelog.app- Helps identify this record for future reference
- Wait 5-10 minutes → Certificate status: "Issued"
12.2 API DNS Record
- Cloudflare → DNS → Add record
- Type: CNAME
- Name:
api-staging - Target:
reelog-lb-staging-809655828.us-east-2.elb.amazonaws.com - Proxy: ✅ Proxied (orange cloud)
- TTL: Auto
- Comment (optional):
Staging API - Points to AWS ALB- Documents that this routes api-staging.reelog.app to the staging load balancer
- Save
12.3 SSL/TLS Settings
- Cloudflare → SSL/TLS → Overview
- SSL/TLS encryption mode: Full (strict)
- Requires valid ACM certificate on Load Balancer
- Provides end-to-end encryption
🐳 Step 13: Build and Push Docker Image
- ECR Console →
reelog-api-staging→ View push commands - Copy login command and run:
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 606532921651.dkr.ecr.us-east-2.amazonaws.com - Build image:
docker build -t reelog-api-staging . - Tag image:
docker tag reelog-api-staging:latest 606532921651.dkr.ecr.us-east-2.amazonaws.com/reelog-api-staging:latest - Push image:
docker push 606532921651.dkr.ecr.us-east-2.amazonaws.com/reelog-api-staging:latest
✅ Step 14: Verify Deployment
-
Test health check (unauthenticated - for load balancer):
curl https://api-staging.reelog.app/healthShould return:
{"status":"healthy","timestamp":"..."}Test authenticated ping (for API monitoring):
curl -H "Authorization: Bearer YOUR_TOKEN" https://api-staging.reelog.app/pingShould return:
"pong (secure)" -
Check ECS service: Tasks should be running and healthy
-
Check Load Balancer: Target group should show healthy targets
-
Check CloudWatch logs: Logs should be appearing
📋 Checklist
- ECR repository created
- RDS database created and accessible
- Valkey cache created (optional)
- Security groups created (LB, API, DB, Valkey)
- Load Balancer created
- Target group created
- ACM certificate validated
- ECS cluster created
- IAM roles created
- Task definition created
- ECS service running
- S3 bucket created
- CloudWatch log group created
- Cloudflare DNS configured
- Docker image pushed
- API accessible at
https://api-staging.reelog.app
💰 Estimated Monthly Costs (Staging)
- ECS Fargate (2 tasks): ~$15/month
- RDS db.t3.micro: ~$15/month (or free tier)
- Valkey cache.t4g.micro: Free tier (750 hours/month) or ~$9.50/month
- Load Balancer: ~$16/month
- Cloudflare: FREE
- S3: ~$1/month
- Total: ~$47-57/month (or ~$32/month with free tier)
Last Updated: Current Date
Region: us-east-2
Domain: reelog.app