Erstellen Sie mit GitHub Action ein Docker-Image, speichern Sie es in Amazon ECR und stellen Sie es in Amazon ECS bereit.
--Punkt
--Erstellen Sie eine Ziel-ECR --Erstellen Sie eine ECR, für die die Bereitstellung erfolgen soll --Erstellen Sie einen AWS IAM-Benutzer zur Verwendung mit GitHub Action (erfordert ECR- und ECS-Berechtigungen).
Fahren Sie mit diesen wie erstellt fort.
Erstellen Sie einen Workflow wie den folgenden und speichern Sie ihn in ".github / workflows /" im Repository mit einem geeigneten Namen wie "deploy-to-ecs.yml". Durch Verschieben des Tags in den Hauptzweig funktioniert dieser Workflow. Das Docker-Image wird in ECR verschoben und in ECS bereitgestellt. Verwenden Sie Githubs Release. Ich gehe davon aus.
.github/workflows/deploy-to-ecs.yml
name: Deploy to ECS
on:
push:
tags:
- v*
env:
ECR_REPOSITORY: your-repository-name
ECS_SERVICE: your-service-name
ECS_CLUSTER: your-cluster-name
jobs:
deploy:
name: Deploy to ECS
if: github.event.base_ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure AWS Credentials #AWS-Zugriffsberechtigungseinstellungen
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: ap-northeast-1
- name: Login to Amazon ECR #ECR-Anmeldevorgang
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Set Docker Tag Env #Ordnen Sie die Docker Image-Version dem Tag zu
run: echo "::IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")" >> $GITHUB_ENV
- name: Build, tag, and push image to Amazon ECR #Docker Image Build&Push
env:
DOCKER_BUILDKIT: 1
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build --cache-from=$ECR_REGISTRY/$ECR_REPOSITORY:latest --build-arg BUILDKIT_INLINE_CACHE=1 -f Dockerfile -t $ECR_REPOSITORY .
docker tag $ECR_REPOSITORY:latest $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker tag $ECR_REPOSITORY:latest $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
- name: Render Amazon ECS task definition for app container #Rendering der ECS-Taskdefinitionsdatei des App-Containers
id: render-app-container
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: .aws/ecs/task-definition.json
container-name: app
image: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
- name: Deploy to Amazon ECS service #Bereitstellung von ECS-Diensten
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-app-container.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: false
Die Funktionsweise des Workflows wird in der Reihenfolge von oben konkret erläutert.
name: Deploy to ECS
Ich habe mich für den Namen des Workflows entschieden. Dieser Name wird angezeigt, wenn Sie den Workflow in der Liste auf der Registerkarte Github-Repository oder Aktion überprüfen. Wenn Sie mehrere Workflows in einer Verifizierungsumgebung oder Produktionsumgebung erstellen, wird empfohlen, den Namen so zu ändern, dass er leicht zu unterscheiden ist.
on:
push:
tags:
- v*
Es funktioniert, wenn Tags, die mit v
beginnen, wie z. B. v1.0.0
, verschoben werden und Release Es wird davon ausgegangen, dass dieser Workflow durch Erstellen von (/ github / Administration-a-Repository / Verwalten von Releases in einem Repository) funktioniert.
Auch diesmal in Jobs, so dass es nicht funktioniert, wenn das Tag in einen anderen Zweig verschoben wird
if: github.event.base_ref == 'refs/heads/main'
Es funktioniert nicht, wenn es nicht der Hauptzweig ist.
Lassen Sie die Beschreibung von "if" weg, damit es funktioniert, wenn es in einen bestimmten Zweig verschoben wird
on:
push:
branches:
- target-branch
Bitte beschreiben Sie als. (Ändern Sie den Zielzweig in den Zweig, der bereitgestellt werden soll.)
Um zu erkennen, dass es funktioniert, wenn ein Tag mit der Beschreibungsmethode "on: push:" in einen bestimmten Zweig verschoben wird
on:
push:
tags:
- v*
branches:
- target-branch
Wenn Sie wie schreiben, ist dies eine oder Bedingung (wenn entweder das Tag oder der Zweig verschoben wird) anstelle der Bedingung und. Geben Sie daher das Ziel-Tag mit on: push:
und das Ziel mit if
an Der Zweig von ist angegeben.
env:
ECR_REPOSITORY: your-repository-name
ECS_SERVICE: your-service-name
ECS_CLUSTER: your-cluster-name
Es wird einer Umgebungsvariablen zugewiesen, um die Beschreibung des Werts zu reduzieren, der im Job häufig verwendet wird. Bitte ändern Sie "Ihr-Name" in den Namen in Ihrer Umgebung
jobs:
deploy:
name: Deploy to ECS
if: github.event.base_ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
Überprüfen Sie den Zielzweig in der Umgebung von "ubuntu-latest" und beginnen Sie mit der Ausführung des Jobs. (Wie bereits erwähnt, wird die "if" -Zeile so geschrieben, dass sie nur im Hauptzweig ausgeführt wird, wenn das Tag verschoben wird. Dies ist nicht erforderlich, wenn die Betriebsbedingung geändert wird, um den Zweig zu verschieben.)
- name: Configure AWS Credentials #AWS-Zugriffsberechtigungseinstellungen
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: ap-northeast-1
Ich bin bei dem AWS-Konto angemeldet, das die ECR zum Pushen und das ECS zum Bereitstellen erstellt hat.
Bereitstellung mithilfe von Githubs Secret (https://docs.github.com/de/free-pro-team@latest/actions/reference/encrypted-secrets) IAM-Zugriff und geheimen Schlüsseln AWS_ACCESS_KEY_ID Bitte registrieren Sie sich mit
und AWS_SECRET_ACCESS_KEY
.
- name: Login to Amazon ECR #ECR-Anmeldevorgang
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
Melden Sie sich bei der ECR des AWS-Kontos an, das Sie in Schritt 5 angemeldet haben.
- name: Set Docker Tag Env #Ordnen Sie die Docker Image-Version dem Tag zu
run: echo "::IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")" >> $GITHUB_ENV
Das Tag wurde so verschoben, dass das Image-Tag von Docker denselben Wert hat wie das Tag von git. Es wird in einem Format wie "v1.0.0" entfernt und der Umgebungsvariablen zugewiesen. Wenn Sie unter den Betriebsbedingungen des Workflows keine Tags verwenden,
run: echo "::IMAGE_TAG=${{ github.sha }}" >> $GITHUB_ENV
Ich denke, es ist eine gute Idee, einen Commit-Hash zu verwenden, um das Image-Tag einzigartig zu machen.
- name: Build, tag, and push image to Amazon ECR #Docker Image Build&Push
env:
DOCKER_BUILDKIT: 1
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build --cache-from=$ECR_REGISTRY/$ECR_REPOSITORY:latest --build-arg BUILDKIT_INLINE_CACHE=1 -f Dockerfile -t $ECR_REPOSITORY .
docker tag $ECR_REPOSITORY:latest $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker tag $ECR_REPOSITORY:latest $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
Wenn Sie ein Docker-Image lokal erstellen, wird der Build mit dem zuvor erstellten Image beschleunigt, aber GitHub Action behält das vorherige Build-Ergebnis nicht bei, sodass die Erstellung jedes Mal einige Zeit in Anspruch nimmt.
Daher wird hier Dockers "Docker-Build --cache-from" verwendet, um den Build zu beschleunigen.
Wir erstellen ein Docker-Image, verschieben das in der Umgebungsvariablen IMAGE_TAG gespeicherte Tag und der Wert ändert sich dynamisch für jede Workflow-Operation, sodass der Wert zum Zeitpunkt des vorherigen Builds verwendet wird. Da es schwierig ist, es zu bekommen, drücke ich auch das neueste Tag und verwende das neueste Tag für das Caching. Auf diese Weise kann der Cache verwendet werden, während er mit dem Release-Tag übereinstimmt.
(DOCKER_BUILDKIT
, BUILDKIT_INLINE_CACHE
wird beschrieben, da --cache-from
verwendet werden muss.)
Hinweis: Wenn Sie den mehrstufigen Build von Docker verwenden, können Sie diese Methode nicht zwischenspeichern, da das Docker-Image nicht den gesamten Build-Prozess enthält. In diesem Fall sollten Sie sich auf [Artikel wie diesen] beziehen (https://engineer.recruit-lifestyle.co.jp/techblog/2020-09-25-docker-build/).
- name: Render Amazon ECS task definition for app container #Rendering der ECS-Taskdefinitionsdatei des App-Containers
id: render-app-container
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: .aws/ecs/task-definition.json
container-name: app
image: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
Um ECS auszuführen, ist eine Aufgabendefinition erforderlich, und es ist erforderlich, die Repository- und Tag-Informationen des Docker-Images zu beschreiben, das dort verwendet werden soll. Daher ist es beim Aktualisieren von DockerImage auch erforderlich, die Aufgabendefinition zu aktualisieren, und dieser Prozess wird ausgeführt.
今回はレポジトリへタスク定義ファイル.aws/ecs/task-definition.json
を作成してあり、そのファイルを呼び出し、Dockerイメージの情報を更新しています。
Referenzbeispiel für task-definition.json
)
{
"containerDefinitions": [
"portMappings": [
{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}
],
"image": "your-image-name",
"name": "app"
}
],
"cpu": "256",
"executionRoleArn": "your-role-name",
"family": "your-family",
"memory": "512",
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc"
}
Lesen von s3 scheint möglich zu sein. Verwalten Sie daher bitte jede Aufgabendefinition, die Sie mögen.
- name: Deploy to Amazon ECS service #Bereitstellung von ECS-Diensten
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-app-container.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: false
Es wird auf der Grundlage der in 9 erstellten Aufgabendefinition für ECS bereitgestellt. Wenn Sie "Wait-for-Service-Stability" auf "true" setzen, können Sie auf den Abschluss der Ausführung warten, bis die Bereitstellung abgeschlossen ist, und den Abschluss der Bereitstellung benachrichtigen. Die Ausführungszeit von Github-Aktionen erhöht sich jedoch. Es besteht die Möglichkeit, dass der Ausführungsrahmen überschritten wird. Es ist auch möglich, den Abschluss der Bereitstellung mit AWS Lambda zu verknüpfen und zu benachrichtigen. Daher wird empfohlen, dies in einer Umgebung mit vielen Bereitstellungen zu tun.
Wenn der obige Ablauf ordnungsgemäß funktioniert, ist die Bereitstellung abgeschlossen.
- name: Run Migrate #Führen Sie die Migration aus
env:
CLUSTER_ARN: your_cluster_arn
ECS_SUBNER_FIRST: your_subnet_first
ECS_SUBNER_SECOND: your_subner_second
ECS_SECURITY_GROUP: your_security_group
run: |
aws ecs run-task --launch-type FARGATE --cluster $ECS_CLUSTER --task-definition ${{ steps.put-migrate-task.outputs.render-app-container }} --network-configuration "awsvpcConfiguration={subnets=[$ECS_SUBNER_FIRST, $ECS_SUBNER_SECOND],securityGroups=[$ECS_SECURITY_GROUP],assignPublicIp=ENABLED}" > run-task.log
TASK_ARN=$(jq -r '.tasks[0].taskArn' run-task.log)
aws ecs wait tasks-stopped --cluster $CLUSTER_ARN --tasks $TASK_ARN
Ich wollte die Datenbank vor der Bereitstellung dieses Mal migrieren, daher habe ich in Schritt 10 einen solchen Job zum ECS hinzugefügt, bevor ich die Aufgabe allein bereitgestellt und ausgeführt habe. Auf diese Weise ist es auch möglich, eine einzelne Aufgabe in Github-Aktionen auszuführen.
Bei der Bereitstellung in ECS gibt es meiner Meinung nach Optionen wie das Kombinieren von AWS CodeBuild und AWS CodePipeline, aber es ist auch möglich, die Bereitstellung einfach mit GitHub Action durchzuführen.
Ich habe sehr viel auf den folgenden Artikel verwiesen.