LoginSignup
4
3

More than 1 year has passed since last update.

Github ActionからECRにpushしてECS Fargateにデプロイする

Last updated at Posted at 2023-03-24

バックエンド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
    • ALB: prod-alb
      • Target Group: prod-backend-api
    • CloudWatch log group: /ecs/prod-backend-api

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
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3