I need some guidance with this pipeline to deploy a test to ECS, i know that a postgres db in a container is not the best solutions compared to RDS and others but i would like at least to know if it is possible hehe. Im stuck with this for days, it just get stuck in part of running wait-for-it.sh file and does not connect to db, i checked in AWS cloudwatch and the db is getting ready to accept connections, but Django never connects to it. Im using a default VPC attached to the ECS cluster and have inside it a security group with inbound rules to allow traffic in port 8000 for ay IP and other for 5432 port that allows traffic to any IP too, what is wrong?
name: CD Pipeline
on:
push:
branches:
- main
jobs:
deploy-ecs:
name: Deploy to ECS
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Log in to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1
- name: Check if backend Docker image exists
id: backend-image-check
run: |
IMAGE_TAG=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest
if aws ecr describe-images --repository-name backend --image-ids imageTag=latest; then
echo "Backend image exists."
echo "::set-output name=exists::true"
else
echo "Backend image does not exist."
echo "::set-output name=exists::false"
fi
- name: Build and push backend Docker image
if: steps.backend-image-check.outputs.exists == 'false'
run: |
docker buildx build --platform linux/amd64,linux/arm64 -f ./backend/DockerfileProd -t ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest --push ./backend
- name: Check if frontend Docker image exists
id: frontend-image-check
run: |
IMAGE_TAG=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest
if aws ecr describe-images --repository-name frontend --image-ids imageTag=latest; then
echo "Frontend image exists."
echo "::set-output name=exists::true"
else
echo "Frontend image does not exist."
echo "::set-output name=exists::false"
fi
- name: Build and push frontend Docker image
if: steps.frontend-image-check.outputs.exists == 'false'
run: |
docker buildx build --platform linux/amd64,linux/arm64 -f ./frontend/DockerfileProd -t ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest --push ./frontend
- name: Install AWS CLI
run: |
sudo apt-get update
sudo apt-get install -y awscli
- name: Create CloudWatch Logs group
run: |
aws logs create-log-group --log-group-name /ecs/kanastra || true
- name: Create ECS Task Definition
run: |
echo '{
"family": "kanastra-task",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "db",
"image": "postgres",
"essential": true,
"memory": 512,
"cpu": 256,
"environment": [
{ "name": "POSTGRES_DB", "value": "kanastra_db" },
{ "name": "POSTGRES_USER", "value": "kanastra_user" },
{ "name": "POSTGRES_PASSWORD", "value": "mypassword" },
{ "name": "POSTGRES_PORT", "value": "5432" }
],
"portMappings": [
{ "containerPort": 5432,
"protocol": "tcp" }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/kanastra",
"awslogs-region": "${{ secrets.AWS_REGION }}",
"awslogs-stream-prefix": "db"
}
}
},
{
"name": "web",
"image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/backend:latest",
"essential": true,
"memory": 512,
"cpu": 256,
"environment": [
{ "name": "DB_NAME", "value": "kanastra_db" },
{ "name": "DB_USER", "value": "kanastra_user" },
{ "name": "DB_PASSWORD", "value": "mypassword" },
{ "name": "DB_HOST", "value": "db" },
{ "name": "DB_PORT", "value": "5432" }
],
"portMappings": [
{ "containerPort": 8000,
"protocol": "tcp" }
],
"command": [
"sh", "-c",
"echo 'Waiting for DB to be ready...' && /usr/local/bin/wait-for-it.sh db:5432 -- echo 'DB is ready, starting application...' && python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/kanastra",
"awslogs-region": "${{ secrets.AWS_REGION }}",
"awslogs-stream-prefix": "web"
}
}
},
{
"name": "frontend",
"image": "${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/frontend:latest",
"essential": true,
"memory": 512,
"cpu": 256,
"portMappings": [
{ "containerPort": 3000, "hostPort": 3000 }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/kanastra",
"awslogs-region": "${{ secrets.AWS_REGION }}",
"awslogs-stream-prefix": "frontend"
}
}
}
],
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"executionRoleArn": "arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/ecsTaskExecutionRole"
}' > ecs-task-def.json
- name: Register ECS Task Definition
run: |
aws ecs register-task-definition
--cli-input-json file://ecs-task-def.json
- name: Create or Update ECS Service
run: |
SERVICE_NAME=${{ secrets.ECS_SERVICE }}
CLUSTER_NAME=${{ secrets.ECS_CLUSTER }}
TASK_DEFINITION=kanastra-task
while true; do
SERVICE_STATE=$(aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME --query 'services[0].status' --output text)
if [ "$SERVICE_STATE" == "ACTIVE" ]; then
echo "Service is active, updating..."
aws ecs update-service
--cluster $CLUSTER_NAME
--service $SERVICE_NAME
--task-definition $TASK_DEFINITION
--force-new-deployment
break
elif [ "$SERVICE_STATE" == "INACTIVE" ] || [ "$SERVICE_STATE" == "None" ]; then
echo "Service is inactive, creating a new service..."
aws ecs create-service
--cluster $CLUSTER_NAME
--service-name $SERVICE_NAME
--task-definition $TASK_DEFINITION
--desired-count 1
--launch-type FARGATE
--network-configuration "awsvpcConfiguration={subnets=[${{ secrets.AWS_SUBNET }}],securityGroups=[${{ secrets.AWS_SECURITY_GROUP }}],assignPublicIp=ENABLED}"
break
else
echo "Service is in state $SERVICE_STATE, waiting for it to become active..."
sleep 30
fi
done
and my wait-for-it.sh file:
#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are available
TIMEOUT=60
QUIET=0
HOST="$1"
PORT="$2"
echo "Waiting for $HOST:$PORT to be available..."
for i in `seq $TIMEOUT` ; do
echo "Attempt $i: Checking connection to $HOST:$PORT..."
nc -zv "$HOST" "$PORT" > /dev/null 2>&1
result=$?
if [ $result -eq 0 ] ; then
echo "Connection to $HOST:$PORT succeeded."
exit 0
fi
echo "Attempt $i: Connection to $HOST:$PORT failed."
sleep 1
done
echo "Operation timed out after $TIMEOUT seconds" >&2
exit 1```
I tried change the localhost from db to localhost but did not work, im expecting the container to do not stop and see this functional, remembering that im pushing images to ECR from a macbook m1, but i think i fixed this in build part and ECS service is working, and db container is good, if was something behind i think i would not have gotten so far to ECS.