GitHub Actions でAmazonECRにdockerイメージをpushする


はじめに

Amazon ECRにGitHubActionsからdockerイメージをPushしてみたので記事にします。

目次

1. 最終的なコード
2. secret機能の利用
3. assume-roleで認証
4. $GITHUB_ENVで環境変数を定義
5. latestの利用

1. 最終的なコード

~/.github/workflows/build.yaml
name: Build and push image to Amazon ECR

on:
  push:
    branches:
      - feature_actions
  workflow_dispatch:

jobs:
  verification-and-build:
    runs-on: ubuntu-latest
    env:
      ECR_REPOSITORY: actions-ecr-demo
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup java
        uses: actions/setup-java@v2
        with:
          distribution: 'adopt'
          java-version: '11'
      - name: Verification
        run: ./gradlew check
      - name: Build
        run: ./gradlew build -x test
      - 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: ap-northeast-1
          role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Set environment variables
        run: |
          echo "IMAGE_TAG=$(echo ${{ github.sha }} | head -c 8)" >> $GITHUB_ENV
          echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}/$ECR_REPOSITORY" >> $GITHUB_ENV
      - name: Build Docker images
        run: docker build -t $ECR_REGISTRY:$IMAGE_TAG -t $ECR_REGISTRY:latest .
      - name: Push image to Amazon ECR
        run: docker push --all-tags $ECR_REGISTRY

2. secret機能の利用

以下の部分はgitのsecrets機能を利用し、コード上で管理したくないアクセスキーなどをマスクするために利用します。

          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          ...
          role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}

GitHubの Settings -> Secretsから設定します。

3. assume-roleで認証

スイッチロール下でIAMユーザを利用している場合は以下のドキュメントにあるようにassume-roleを利用して認証します。
"Configure AWS Credentials" Action For GitHub Actions

  role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}

注意点として、スイッチ先の信頼ポリシーとスイッチ元の自身のIAMユーザにセッションタグへのアクセスを許可する必要があります。

スイッチ先の信頼ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<acountId>:root"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"  # "sts:TagSession"を追加
      ],
      "Condition": {}
    }
  ]
}
IAMユーザに付与するポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"  # "sts:TagSession"をIAMユーザにも追加
      ],
      "Resource": "arn:aws:iam::{スイッチ先のアカウントID}:role/{付与するrole}"
    }
  ]
}

以下のエラーが発生し、セッションタグの利用について特に必要でなければセッションタグの設定をスキップすることもできます。

User: arn:aws:iam::***:user/{userName} is not authorized to perform: sts:TagSession on resource: ***
  role-skip-session-tagging: true

4. $GITHUB_ENVで環境変数を定義

特定のstepで$GITHUB_ENVに使用したい値をリダイレクトすることで以降のstepで使用可能となります。($GITHUB_ENVにリダイレクトしたstep内では使用できないので注意して下さい)
用途としては、以下の場合は考えられます。

  • 後続のstepで何度も使用したい
  • jobの環境変数のように静的な値ではなく、step実行時に生成される動的は値を環境変数として使用したい

5. latestの利用

dockerイメージのイメージタグをlatestとして設定したい場合は、commitのshaハッシュ値を同時に設定すると良いです。
以下の画像のようにlatestのみの場合は新しくlatestタグを設定した時にイメージタグが設定されていない状態になるのを回避できます。