GitHub ActionsからAmazon ECSにアプリをデプロイ

# 前提

* DockerレジストリにはAmason ECRを利用している
* ECSにてすでにタスク定義とサービスが動作済み。

(筆者は https://qiita.com/VA_nakatsu/items/c8a4b24b8cffd0e9047b の記事を参考にECS環境を構築しました。)

# GitHub Actions で利用するIAMユーザ作成 & ポリシーアタッチ

はじめに、GitHub ActionsからAWSへアクセス操作をするユーザ(今回はgithub.actionsという名前)を作成し、ACCESS KEYとSECRET KEYを取得します。

その後、そのユーザに対しECRとECSへの操作をするためのポリシーをアタッチします。

![スクリーンショット 2020-04-09 21.37.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/e3c15a19-1923-61c3-4ad1-970f238f7d21.png)

ECR用に`AmazonEC2ContainerRegistryPowerUser`、ECS用に`AmazonECS_FullAccess`をアタッチさせています。

# GitHubレポジトリへSecret Key設定

GitHub Actionsで利用するためのシークレットな値をGitHubレポジトリ上のSecretに設定します。

![スクリーンショット 2020-04-09 22.11.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/64efff0d-7fc2-199a-3104-da32db319228.png)

今回は3つの値を設定します。

* `AWS_ACCESS_KEY_ID`: github.actions ユーザのACCESS KEY
* `AWS_SECRET_ACCESS_KEY`: github.actions ユーザのSECRET KEY
* `AWS_ECR_REPO_NAME`: ECR上で作成済みのImage URI(例: `XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app`)

# タスク定義ファイル task-definition.json の用意

ECSにデプロイするためにタスク定義ファイルJSONを用意します。

既に動作しているECSから下記スクリーンショットのようにタスク定義のJSONを取得します。(AWS CLIからも取得可能です。)

<img width="1019" alt="スクリーンショット 2020-04-06 22.19.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/fb5c3b17-6674-0467-a4fa-513bd2982927.png">

コピペしたままでは、下記スクリーンショットのように無駄なフィールドが存在しECSタスクリビジョン更新の際にWarningが出ることがわかりました。

<img width="1124" alt="スクリーンショット 2020-04-07 22.07.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/ff591f40-42d2-e0e0-8cf0-49342ee6cfe5.png">

Warningに出た以下のフィールドをJSONから削除します。

* `compatibilities`
* `taskDefinitionArn`
* `requiresAttributes`
* `revision`
* `status`

私はjqコマンドを利用して以下のように上記フィールドを削除しました。

```
pbpaste | jq "del(.compatibilities)" | jq "del(.taskDefinitionArn)" | jq "del(.requiresAttributes)" | jq "del(.revision)" | jq "del(.status)"
```

# GitHub Actions Workflow Yamlファイルの更新

GitHub Actionsのワークフロー用Yamlファイルにデプロイするためのジョブを追加します。

ファイル内の`app-service`、`app-ecs-cluster`などは適宜置き換えてください。

```yaml:.github/workflows/workflow.ymlの一部
  deploy:
    name: Deploy app
    needs: test
    if: github.ref == 'refs/heads/master' # masterブランチのときだけデプロイ
    runs-on: ubuntu-latest
    steps:

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

    - name: Configure AWS Credentials # AWSアクセス権限設定
      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ログイン処理
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push image to Amazon ECR # ECRイメージPush
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPO_NAME }}
      run: |
        IMAGE_TAG=latest
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

    - name: Render Amazon ECS task definition # ECSタスク定義ファイルレンダリング
      id: render-container
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: aws/task-definition.json # レポジトリ以下のタスク定義ファイルがあるPath
        container-name: app-container-name
        image: XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest

    - name: Deploy to Amazon ECS service # ECSサービスデプロイ
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.render-container.outputs.task-definition }}
        service: app-service
        cluster: app-ecs-cluster
```

ここでは、AWS公式のGitHub Actionsワークフロー4つを利用しています。 https://github.com/aws-actions 

ステップの内容はファイル内のコメントをご参照ください。

# 参考

* https://dev.classmethod.jp/articles/github-action-ecr-push/
* https://dev.classmethod.jp/articles/describe-task-definition-to-register-task-definition/