Jiffoo Docs
Deployment

AWS ECS/Fargate Deployment

Deploy Jiffoo Mall on AWS using ECS and Fargate

AWS ECS/Fargate Deployment

Prerequisites

  • AWS CLI 2.0+
  • AWS Account with appropriate IAM permissions
  • Docker for building images
  • ECR repositories created for each service

Architecture Overview

This guide deploys Jiffoo Mall using:

  • ECS Fargate for container orchestration
  • Application Load Balancer for traffic distribution
  • RDS PostgreSQL for database
  • ElastiCache Redis for caching
  • Secrets Manager for sensitive configuration

Quick Start

1. Create ECR Repositories

aws ecr create-repository --repository-name jiffoo/api
aws ecr create-repository --repository-name jiffoo/shop
aws ecr create-repository --repository-name jiffoo/admin

2. Build and Push Images

# Login to ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-east-1.amazonaws.com

# Build and push API
docker build -t jiffoo/api -f apps/api/Dockerfile .
docker tag jiffoo/api:latest <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/api:latest
docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/api:latest

# Build and push Shop
docker build -t jiffoo/shop -f apps/shop/Dockerfile .
docker tag jiffoo/shop:latest <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/shop:latest
docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/shop:latest

# Build and push Admin
docker build -t jiffoo/admin -f apps/admin/Dockerfile .
docker tag jiffoo/admin:latest <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/admin:latest
docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/admin:latest

3. Create RDS Database

aws rds create-db-instance \
  --db-instance-identifier jiffoo-db \
  --db-instance-class db.t3.micro \
  --engine postgres \
  --engine-version 15.3 \
  --master-username postgres \
  --master-user-password <your-password> \
  --allocated-storage 20 \
  --vpc-security-group-ids <security-group-id> \
  --db-subnet-group-name <subnet-group-name>

4. Create ElastiCache Redis

aws elasticache create-cache-cluster \
  --cache-cluster-id jiffoo-redis \
  --cache-node-type cache.t3.micro \
  --engine redis \
  --num-cache-nodes 1 \
  --security-group-ids <security-group-id> \
  --cache-subnet-group-name <subnet-group-name>

ECS Task Definitions

API Task Definition

{
  "family": "jiffoo-api",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "containerDefinitions": [
    {
      "name": "api",
      "image": "<account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/api:latest",
      "portMappings": [
        {
          "containerPort": 3001,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ],
      "secrets": [
        {
          "name": "DATABASE_URL",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:<account-id>:secret:jiffoo/database-url"
        },
        {
          "name": "REDIS_URL",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:<account-id>:secret:jiffoo/redis-url"
        },
        {
          "name": "JWT_SECRET",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:<account-id>:secret:jiffoo/jwt-secret"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/jiffoo-api",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Shop Task Definition

{
  "family": "jiffoo-shop",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [
    {
      "name": "shop",
      "image": "<account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/shop:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NEXT_PUBLIC_API_URL",
          "value": "https://api.yourdomain.com"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/jiffoo-shop",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Admin Task Definition

{
  "family": "jiffoo-admin",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "containerDefinitions": [
    {
      "name": "admin",
      "image": "<account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/admin:latest",
      "portMappings": [
        {
          "containerPort": 3003,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NEXT_PUBLIC_API_URL",
          "value": "https://api.yourdomain.com"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/jiffoo-admin",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Create ECS Services

1. Create ECS Cluster

aws ecs create-cluster --cluster-name jiffoo-cluster

2. Register Task Definitions

aws ecs register-task-definition --cli-input-json file://api-task-def.json
aws ecs register-task-definition --cli-input-json file://shop-task-def.json
aws ecs register-task-definition --cli-input-json file://admin-task-def.json

3. Create Load Balancers

# Create Application Load Balancer
aws elbv2 create-load-balancer \
  --name jiffoo-alb \
  --subnets <subnet-id-1> <subnet-id-2> \
  --security-groups <security-group-id>

# Create target groups
aws elbv2 create-target-group \
  --name jiffoo-api-tg \
  --protocol HTTP \
  --port 3001 \
  --vpc-id <vpc-id> \
  --target-type ip \
  --health-check-path /health

aws elbv2 create-target-group \
  --name jiffoo-shop-tg \
  --protocol HTTP \
  --port 3000 \
  --vpc-id <vpc-id> \
  --target-type ip

aws elbv2 create-target-group \
  --name jiffoo-admin-tg \
  --protocol HTTP \
  --port 3003 \
  --vpc-id <vpc-id> \
  --target-type ip

4. Create ECS Services

aws ecs create-service \
  --cluster jiffoo-cluster \
  --service-name jiffoo-api \
  --task-definition jiffoo-api \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<subnet-id-1>,<subnet-id-2>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" \
  --load-balancers "targetGroupArn=<target-group-arn>,containerName=api,containerPort=3001"

Secrets Management

Store sensitive configuration in AWS Secrets Manager:

# Database URL
aws secretsmanager create-secret \
  --name jiffoo/database-url \
  --secret-string "postgresql://postgres:password@<rds-endpoint>:5432/jiffoo"

# Redis URL
aws secretsmanager create-secret \
  --name jiffoo/redis-url \
  --secret-string "redis://<elasticache-endpoint>:6379"

# JWT Secret
aws secretsmanager create-secret \
  --name jiffoo/jwt-secret \
  --secret-string "<your-jwt-secret>"

Database Migrations

Run migrations using ECS Task:

aws ecs run-task \
  --cluster jiffoo-cluster \
  --task-definition jiffoo-api \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<subnet-id>],securityGroups=[<security-group-id>],assignPublicIp=ENABLED}" \
  --overrides '{"containerOverrides":[{"name":"api","command":["pnpm","db:push"]}]}'

CloudWatch Logs

View logs for your services:

# API logs
aws logs tail /ecs/jiffoo-api --follow

# Shop logs
aws logs tail /ecs/jiffoo-shop --follow

# Admin logs
aws logs tail /ecs/jiffoo-admin --follow

Scaling

Manual Scaling

aws ecs update-service \
  --cluster jiffoo-cluster \
  --service jiffoo-api \
  --desired-count 4

Auto Scaling

# Register scalable target
aws application-autoscaling register-scalable-target \
  --service-namespace ecs \
  --resource-id service/jiffoo-cluster/jiffoo-api \
  --scalable-dimension ecs:service:DesiredCount \
  --min-capacity 2 \
  --max-capacity 10

# Create scaling policy
aws application-autoscaling put-scaling-policy \
  --service-namespace ecs \
  --resource-id service/jiffoo-cluster/jiffoo-api \
  --scalable-dimension ecs:service:DesiredCount \
  --policy-name cpu-scaling \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration file://scaling-policy.json

scaling-policy.json:

{
  "TargetValue": 75.0,
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
  },
  "ScaleOutCooldown": 60,
  "ScaleInCooldown": 60
}

Monitoring

CloudWatch Dashboards

Create a dashboard to monitor your services:

aws cloudwatch put-dashboard \
  --dashboard-name jiffoo-metrics \
  --dashboard-body file://dashboard.json

CloudWatch Alarms

# High CPU alarm
aws cloudwatch put-metric-alarm \
  --alarm-name jiffoo-api-high-cpu \
  --alarm-description "Alert when API CPU exceeds 80%" \
  --metric-name CPUUtilization \
  --namespace AWS/ECS \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2

Troubleshooting

Service Not Starting

Check service events:

aws ecs describe-services \
  --cluster jiffoo-cluster \
  --services jiffoo-api

Task Failures

View task details:

aws ecs describe-tasks \
  --cluster jiffoo-cluster \
  --tasks <task-id>

Database Connection Issues

Verify security groups allow traffic from ECS tasks to RDS:

aws ec2 describe-security-groups --group-ids <security-group-id>

Container Health Checks

Check target group health:

aws elbv2 describe-target-health \
  --target-group-arn <target-group-arn>

Cost Optimization

  • Use Fargate Spot for non-critical workloads
  • Enable ECS Service Auto Scaling to match demand
  • Use RDS Reserved Instances for production databases
  • Configure CloudWatch Logs retention to reduce storage costs
  • Use S3 Lifecycle Policies for old logs and backups

CI/CD Integration

Update your deployment pipeline to push to ECS:

# Build and push new image
docker build -t jiffoo/api -f apps/api/Dockerfile .
docker tag jiffoo/api:latest <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/api:latest
docker push <account-id>.dkr.ecr.us-east-1.amazonaws.com/jiffoo/api:latest

# Force new deployment
aws ecs update-service \
  --cluster jiffoo-cluster \
  --service jiffoo-api \
  --force-new-deployment

On this page