バックエンドAPIをGithub ActionからECS Fargateにデプロイするサンプル設定をまとめてみました。
設定自体はNest.js(Node.js)やRails, Laravelなど他のWebフレームワークでも同様だと思います。
AWS環境の構成
AWSの環境はおおよそこんな感じの構成です。
- IAM user: prod-backend-api-deploy
- 許可するポリシー
- ECR Push
- ECS Deploy
- 許可するポリシー
- ECR: backend-api
- ECS: prod-backend-api
- VPC: prod
- subnet: internal
- security group: 80番ポートへのアクセスを許可
- execution role: prod-backend-api-ecs-execution
- 許可するポリシー
- ECR Pull
- Log Write
- 許可するポリシー
- task role: prod-backend-api-ecs-task
- 許可するポリシー(SecretManagerの認証情報を使ってRDSに接続する場合)
- Secret Manager Read
- RDS Data Full Access
- 許可するポリシー(SecretManagerの認証情報を使ってRDSに接続する場合)
- ALB: prod-alb
- Target Group: prod-backend-api
- CloudWatch log group: /ecs/prod-backend-api
- VPC: prod
Github Actionの作成
- 事前準備
- AWSのIAMユーザ(prod-backend-api-deploy)のアクセスキーを発行して、Githubリポジトリのproduction環境の環境変数に認証情報を設定しておきます。
.github/workflows/deploy-prod.yml
name: Deploy to Production
on:
push:
branches:
- main
workflow_dispatch:
env:
AWS_REGION: ap-northeast-1
AWS_ACCOUNT_ID: xxx
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ECR_REPOSITORY: backend-api
ECS_CLUSTER_NAME: prod-backend-api
ECS_SERVICE_NAME: backend-api
IMAGE_TAG: ${{ github.sha }}
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
steps:
- name: Checkout code
uses: actions/checkout@v2
- 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: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build and Push Docker image to ECR
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
docker build . -f ./docker/api/Dockerfile --target production --tag ${{ env.REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
docker push ${{ env.REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
with:
task-definition: .aws/task-definition.prod.json
container-name: backend-api
image: ${{ env.REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
- name: Deploy ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
cluster: ${{ env.ECS_CLUSTER_NAME }}
service: ${{ env.ECS_SERVICE_NAME }}
wait-for-service-stability: true
Github Actionで参照するタスク定義の内容はこんな感じです。
.aws/task-definision.prod.json
{
"requiresCompatibilities": [ "FARGATE" ],
"family": "prod-backend-api",
"containerDefinitions": [
{
"name": "prod-backend-api",
"environment": [],
"essential": true,
"portMappings": [
{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/prod-backend-api",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "awslogs-prod-api"
}
}
}
],
"volumes": [],
"networkMode": "awsvpc",
"memory": "512",
"cpu": "256",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"taskRoleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/prod-backend-api-ecs-task",
"executionRoleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/prod-backend-api-ecs-execution"
}
テスト用のDockerfileはこんな感じのものを用意すればOKです。
./docker/api/Dockerfile
FROM httpd:2.4 as production
RUN mkdir /usr/local/apache2/conf/include/
RUN echo 'Include conf/include/*.conf ' >> /usr/local/apache2/conf/httpd.conf
RUN echo 'ServerName localhost:80' > /usr/local/apache2/conf/include/test.conf