我需要一些有关此管道的指导来将测试部署到 ECS,我知道与 RDS 和其他解决方案相比,容器中的 postgres 数据库并不是最好的解决方案,但我至少想知道是否可能,呵呵。我被这个问题困扰了好几天,它只是卡在运行 wait-for-it.sh 文件的一部分并且无法连接到数据库,我检查了 AWS cloudwatch 并且数据库正准备接受连接,但 Django 从未连接到它。我使用连接到 ECS 集群的默认 VPC,并在其内部有一个安全组,该安全组具有入站规则,允许 y IP 的端口 8000 中的流量,以及其他 5432 端口中的流量,也允许流量到达任何 IP,有什么问题吗?
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
和我的 wait-for-it.sh 文件:
#!/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.
您正在部署到 Fargate。使用 Fargate,在同一任务中运行的所有容器共享一个弹性网络接口,并且可以通过各自的端口通过
localhost
或 127.0.0.1
相互通信。这记录在此处。
如果你改变这个:
{ "name": "DB_HOST", "value": "db" },
对此:
{ "name": "DB_HOST", "value": "127.0.0.1" },
应该可以。