ECS 在推送到 EC2 时不会删除旧的 docker 容器

问题描述 投票:0回答:1

我的自动化工作流程遇到问题。当前正在运行的内容:当我将代码更改推送到我的 github 存储库上的 main 时,它会将 Docker 映像推送到具有唯一标记名称的 ECR,ECS 从那里提取新的 docker 映像并创建新的任务定义和修订。我的旧 ECS 服务会缩小规模,新的 ECS 服务会扩大规模。然后该图像会正确发送到 EC2。我正在使用 vite 和 NPM 运行一个 Web 应用程序,我遇到的问题是,当新的 docker 容器弹出时,旧的 docker 容器永远不会被删除。在我的 ECS 中,我将最小和最大健康百分比设置为 0% 和 100%,以保证旧服务在新服务开始之前完全缩减。

因此,我必须手动通过 SSH 连接到我的 EC2 实例并运行此命令

docker stop CONTAINER_ID
docker rm c184c8ffdf91

然后我必须手动运行新容器才能让我的 Web 应用程序显示在 docker 上

run -d -p 4173:4173 ***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:IMAGE_TAG

这是我可以让我的网络应用程序使用主程序中的新代码进行更新的唯一方法,但我希望这是完全自动化的,这看起来已经完成了 99% 的工作。

My github workflow file

name: Deploy to AWS ECR

on:
  push:
    branches:
      - main 

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ***
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: us-east-2

    - name: Login to Amazon ECR
      uses: aws-actions/amazon-ecr-login@v2

    - name: Build, tag, and push image to Amazon ECR
      id: build-and-push
      run: |
        TIMESTAMP=$(date +%Y%m%d%H%M%S)
        COMMIT_SHA=$(git rev-parse --short HEAD)
        IMAGE_TAG=${TIMESTAMP}-${COMMIT_SHA}
        docker build -t aguacero/frontend:${IMAGE_TAG} .
        docker tag aguacero/frontend:${IMAGE_TAG}***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:${IMAGE_TAG}
        docker push ***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:${IMAGE_TAG}
        echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV

    - name: Retrieve latest task definition
      id: get-task-def
      run: |
        TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition aguacero-frontend)
        echo "$TASK_DEFINITION" > task-def.json

    - name: Update task definition
      id: update-task-def
      run: |
        NEW_IMAGE="***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:${{ env.IMAGE_TAG }}"
        UPDATED_TASK_DEFINITION=$(jq --arg IMAGE "$NEW_IMAGE" \
          '{ 
            family: .taskDefinition.family,
            containerDefinitions: (.taskDefinition.containerDefinitions | map(if .name == "aguacero-frontend" then .image = $IMAGE else . end)),
            taskRoleArn: .taskDefinition.taskRoleArn,
            executionRoleArn: .taskDefinition.executionRoleArn,
            networkMode: .taskDefinition.networkMode,
            cpu: .taskDefinition.cpu,
            memory: .taskDefinition.memory,
            requiresCompatibilities: .taskDefinition.requiresCompatibilities,
            volumes: .taskDefinition.volumes
          }' task-def.json)
        echo "$UPDATED_TASK_DEFINITION" > updated-task-def.json

    - name: Log updated task definition
      run: |
        echo "Updated Task Definition:"
        cat updated-task-def.json

    - name: Register new task definition
      id: register-task-def
      run: |
        NEW_TASK_DEFINITION=$(aws ecs register-task-definition --cli-input-json file://updated-task-def.json)
        NEW_TASK_DEFINITION_ARN=$(echo $NEW_TASK_DEFINITION | jq -r '.taskDefinition.taskDefinitionArn')
        echo "NEW_TASK_DEFINITION_ARN=${NEW_TASK_DEFINITION_ARN}" >> $GITHUB_ENV

    - name: Update ECS service
      run: |
        aws ecs update-service --cluster frontend --service aguacero-frontend --task-definition ${{ env.NEW_TASK_DEFINITION_ARN }} --force-new-deployment --region us-east-2

我的 DOCKERFILE

FROM node:18.16.0-slim

WORKDIR /app

ADD . /app/
WORKDIR /app/aguacero

RUN rm -rf node_modules
RUN npm install
RUN npm run build

EXPOSE 4173

CMD [ "npm", "run", "serve" ]

我最新推送到 main 的任务定义

{
    "family": "aguacero-frontend",
    "containerDefinitions": [
        {
            "name": "aguacero-frontend",
            "image": "***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:20241003154856-60bb1fd",
            "cpu": 1024,
            "memory": 512,
            "memoryReservation": 512,
            "portMappings": [
                {
                    "name": "aguacero-frontend-4173-tcp",
                    "containerPort": 4173,
                    "hostPort": 4173,
                    "protocol": "tcp",
                    "appProtocol": "http"
                }
            ],
            "essential": true,
            "environment": [
                {
                    "name": "VITE_HOST_URL",
                    "value": "http://0.0.0.0:8081"
                },
                {
                "name": "ECS_IMAGE_CLEANUP_INTERVAL",
                "value": "3600"
                },
                {
                "name": "ECS_IMAGE_PULL_BEHAVIORL",
                "value": "true"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/aguacero-frontend",
                    "awslogs-create-group": "true",
                    "awslogs-region": "us-east-2",
                    "awslogs-stream-prefix": "ecs"
                }
            },
            "systemControls": []
        }
    ],
    "taskRoleArn": "arn:aws:iam::***:role/ecsTaskExecutionRole",
    "executionRoleArn": "arn:aws:iam::***:role/ecsTaskExecutionRole",
    "networkMode": "awsvpc",
    "requiresCompatibilities": [
        "EC2"
    ],
    "cpu": "1024",
    "memory": "512"
}

这是我运行 docker ps 时的样子,新容器在那里,但旧容器在那里并在端口 4173 上运行。请注意,持续 2 小时的推送与持续 1 小时的推送具有不同的标签

CONTAINER ID   IMAGE                                                                                   COMMAND                  CREATED             STATUS                  PORTS                                       NAMES
9ed96fe29eb5   ***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:20241003154856-60bb1fd   "docker-entrypoint.s…"   Up 1 hour    Up 1 hour                                                    ecs-aguacero-frontend-33-aguacero-frontend-8ae98bdfc1dbe985c501
b78be6681093   amazon/amazon-ecs-pause:0.1.0                                                           "/pause"                 Up 1 hour   Up 1 hour                                                  ecs-aguacero-frontend-33-internalecspause-9e8dbcc4bebec0b87500
1a70ab03320c   ***.dkr.ecr.us-east-2.amazonaws.com/aguacero/frontend:20241003153758-add572a   "docker-entrypoint.s…"   Up 2 hours   Up 2 hours        0.0.0.0:4173->4173/tcp, :::4173->4173/tcp   sad_shannon
3e697581a7a1   amazon/amazon-ecs-agent:latest                                                          "/agent"                 19 hours ago        Up 19 hours (healthy)                                               ecs-agent
amazon-web-services docker amazon-ec2 amazon-ecs amazon-ecr
1个回答
0
投票

问题是:

  1. 您手动登录 EC2 并再次运行该任务,以便在 EC2 实例上公开该任务的端口。这是规避 ECS 容器管理,从而导致后续任务部署出现问题。
  2. 您想通过 EC2 实例的公有 IP 地址访问 ECS 任务,但无法访问。

解决方案是从为 ECS 任务分配单独的 IP 地址的网络模式

awsvpc
切换到使用 EC2 实例的网络执行 ECS 任务的网络模式
host
。之后,您可以通过 EC2 实例的公共 IP 地址访问该任务,现在您可以让 ECS 完成部署和管理容器的工作。

© www.soinside.com 2019 - 2024. All rights reserved.