【AWS】GitHub ActionsでECR publicにimageをpushしてSlack通知をする

投稿日:

はじめに

とある事情により、DockerイメージをECR publicで管理することになりました。
※ publicレジストリしか使えんかった。。

そして、管理する上で

  • imageのビルド、ECRへのpush作業が必要だよね
  • そこはさすがに自動化したいよね
    • 属人化を防ぎたいよね
  • ついでにpushが終わったらSlackに通知したいよね

と思うのが人間の性、心情というものです。
というわけで、今回はそのあたりをまるっとGitHub Actionsでこしらえてみたお話を書いてみます。

ECR(private)に対する諸々の手順(認証からpushまで)をまとめたGitHub Actionsはググるとまぁまぁ出たのですが、ECR publicでの作業(特に認証周り)に対するGitHub Actionsがなかなか見つからなかったので、似たような悩みを持つ誰かの参考になればこれ幸いです。
※ とは言っても、ECR(private)での作業とほぼ変わらないです
※ 後述しますが、利用するactionsがちょっと違うだけ

リポジトリ

リポジトリの作成は、以下の記事を参考に作成しました。

これにより、public.ecr.aws/レジストリ/リポジトリ名 形式のURIが作成できます。

ポリシー

IAMグループ(IAMユーザー)にアタッチするポリシーを設定する必要がありますが、自分は以下の通りに設定しました。

設定

Elastic Container Registry Publicと、STSにポリシーを設定します。

Elastic Container Registry Public

サービス

Elastic Container Registry Publicを選択します。

アクセスレベル
  • 読み込み
    • BatchCheckLayerAvailability
    • GetAuthorizationToken
  • 書き込み
    • CompleteLayerUpload
    • InitiateLayerUpload
    • UploadLayerPart
    • PutImage

を選択します。

リソース

リソースタブを開いて、リソースは指定しつつ、このアカウント内のいずれかのチェックボックスをオンにします。

そうすると、arn:aws:ecr-public::{account-id}:repository/*この形のARNが設定されます。
※ もちろんリポジトリは指定してもいいです

STS

サービス

STSを選択します。

アクセスレベル
  • 読み込み
    • GetServiceBearerToken

を選択します。
GetAuthorizationToken – Amazon Elastic Container Registry Public に、This API requires the ecr-public:GetAuthorizationToken and sts:GetServiceBearerToken permissions.とあったのでGetServiceBearerTokenも追加しました

Json

jsonはこうなります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr-public:InitiateLayerUpload",
                "ecr-public:UploadLayerPart",
                "ecr-public:PutImage",
                "ecr-public:CompleteLayerUpload",
                "ecr-public:BatchCheckLayerAvailability"
            ],
            "Resource": "arn:aws:ecr-public::{account-id}:repository/*" // account-idはそれぞれで変わります
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "ecr-public:GetAuthorizationToken",
                "sts:GetServiceBearerToken"
            ],
            "Resource": "*"
        }
    ]
}

ポリシーの作成については以下を参考にしました。

GitHub Actions

GitHub Actionsは以下のとおりです。
タグのpushをトリガーとして動きます。
vx.x.x形式(v*)のタグ、v1.0.0とかv0.1.0-devとか、要はv始まりのタグを対象としています

.github\workflows\run-build-and-push.yml とします。

name: Build and Push to ECR Public

on:
  push:
    tags:
      - v*

jobs:
  build-and-push:

    runs-on: ubuntu-latest

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

      - name: Login to Public ECR
        uses: docker/login-action@v1
        with:
          registry: public.ecr.aws
          username: ${{ secrets.AWS_ACCESS_KEY_ID }}
          password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        env:
          AWS_REGION: us-east-1

      - name: Build, tag, and push image to Amazon ECR Public
        id: build-and-push-tag
        env:
          ECR_REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_NAME }}
                    ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPOSITORY_NAME }}
        run: |
          IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
          docker build -t public.ecr.aws/$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push public.ecr.aws/$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo ::set-output name=version::$IMAGE_TAG

      - name: Slack Notification
        if: success()
        run: |
          jq -n --arg titleLink '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' '{
            attachments: [{
              pretext: ":white_check_mark: ECR publicに最新imageのpushが完了しました",
              color: "good",
              title: $titleLink,
              title_link: $titleLink,
              fields: [
                {
                  "title": "Tag",
                  "value": "${{ steps.build-and-push-tag.outputs.version }}",
                }
              ]
            }]
          }' | curl ${{ secrets.SLACK_WEBHOOK_URL }} -X POST -H 'Content-Type: application/json' -d @-

Secrets

GitHubのSecretsは以下のとおりとしています。

キー名
AWS_ACCESS_KEY_ID AWS アクセスキーID
AWS_SECRET_ACCESS_KEY AWS シークレットアクセスキー
AWS_ECR_REGISTRY_NAME ECR publcリポジトリ のレジストリ名 
AWS_ECR_REPOSITORY_NAME ECR publcリポジトリ のリポジトリ名
SLACK_WEBHOOK_URL Slack通知用WebHook URL

ECR publicでの認証

このアクションの肝が、この部分です。

- name: Login to Public ECR
  uses: docker/login-action@v1
  with:
    registry: public.ecr.aws
    username: ${{ secrets.AWS_ACCESS_KEY_ID }}
    password: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  env:
    AWS_REGION: us-east-1

これで、ECR publicにログインして認証してくれています。
このアクションは、

を利用しています。利用方法は、with

  • registrypublic.ecr.aws
  • usernameAWS アクセスキーID
  • passwordAWS シークレットアクセスキー

を指定すればいいだけです。
envに関して今の所、リージョンはus-ease-1だけっぽいので設定しなくてもいいです

超簡単、これで認証OKです。しかも何より、Verified creatorです。最高!!

ビルド && プッシュ

以下で、imageをビルドしてECRへpushしています。

- name: Build, tag, and push image to Amazon ECR Public
  id: build-and-push-tag
  env:
    ECR_REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_NAME }}
    ECR_REPOSITORY: ${{ secrets.AWS_ECR_REPOSITORY_NAME }}
  run: |
    IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
    docker build --no-cache -t public.ecr.aws/$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
    docker push public.ecr.aws/$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
    echo ::set-output name=version::$IMAGE_TAG

IMAGE_TAGはSlack通知で利用するので::set-outputを使って出力パラメータを設定しています。
こうすると、${{ steps.build-and-push-tag.outputs.version }}で利用可能になります。
※ ちなみに、IMAGE_TAGはIMAGE_TAG=${GITHUB_REF##*/}でも取れます
GitHub ActionでDockerコンテナをビルドしてAmazon ECRに保存する | DevelopersIO を参考にさせていただきました

Slack通知

最後にSlack通知を行っています。

- name: Slack Notification
  if: success()
  run: |
    jq -n --arg titleLink '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}' '{
      attachments: [{
        pretext: ":white_check_mark: ECR publicに最新imageのpushが完了しました",
        color: "good",
        title: $titleLink,
        title_link: $titleLink,
        fields: [
          {
            "title": "Tag",
            "value": "${{ steps.build-and-push-tag.outputs.version }}",
          }
        ]
      }]
    }' | curl ${{ secrets.SLACK_WEBHOOK_URL }} -X POST -H 'Content-Type: application/json' -d @-

$titleLinkは、実行されたアクションへのリンクになります。
成功すると、こんな通知が届くはずです。

Slack通知を行うactionsでVerified creatorが付いているものがなかなか見つからなかったので、どうしよっかなぁと思っていたのですが単純にcurlで実行できそうだったのでcurlで直接slackのwebhookを叩いて通知を行うようにしています。
if: success()で、前の処理に成功していたら通知を行うようにしています
※ 通知が来なかったらビルドかpushに失敗しています
※ 失敗時にも通知したいとなったら、if: failure()を使えばいいかと思います

こちらを参考にしました。まじで感謝です。

これで、何かしらの修正(Dockerfileとか)などでimageを作成/更新した後は、タグをつけてリポジトリにpushすれば、ECR publicにpushされるようになりました。めでたしめでたし。

おわりに

はっぴーはろうぃーん🎃👻
※ 2021年10月31日 PM11:45 に公開されています

作成者: shimabox

Web系のプログラマをやっています。 なるべく楽しく生きていきたい。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください