我的自动化工作流程遇到问题。当前正在运行的内容:当我将代码更改推送到我的 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
问题是:
解决方案是从为 ECS 任务分配单独的 IP 地址的网络模式
awsvpc
切换到使用 EC2 实例的网络执行 ECS 任务的网络模式 host
。之后,您可以通过 EC2 实例的公共 IP 地址访问该任务,现在您可以让 ECS 完成部署和管理容器的工作。