はじめに
とある事情により、DockerイメージをECR public
で管理することになりました。
※ publicレジストリしか使えんかった。。
そして、管理する上で
- imageのビルド、ECRへのpush作業が必要だよね
- そこはさすがに自動化したいよね
- 属人化を防ぎたいよね
- ついでにpushが終わったらSlackに通知したいよね
と思うのが人間の性、心情というものです。
というわけで、今回はそのあたりをまるっとGitHub Actions
でこしらえてみたお話を書いてみます。
ECR(private)に対する諸々の手順(認証からpushまで)をまとめたGitHub Actionsはググるとまぁまぁ出たのですが、ECR publicでの作業(特に認証周り)に対するGitHub Actionsがなかなか見つからなかったので、似たような悩みを持つ誰かの参考になればこれ幸いです。
※ とは言っても、ECR(private)での作業とほぼ変わらないです
※ 後述しますが、利用するactionsがちょっと違うだけ
リポジトリ
リポジトリの作成は、以下の記事を参考に作成しました。
- ECRをパブリックレジストリとして利用可能になりました! #reinvent | DevelopersIO
- 現在はまたUIが変わっていますけれども、やることは一緒なので迷わないと思います
これにより、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を利用してECRのリポジトリにpushしてみる | SEEDS Creators’ Blog | 株式会社シーズ
- pahud/ecr-public-action
- 上記ブログのポリシー設定を、こちらのリポジトリの内容を参考にして
ecr-public
用に置き換えました
- 上記ブログのポリシー設定を、こちらのリポジトリの内容を参考にして
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にログインして認証してくれています。
このアクションは、
- Docker Login · Actions · GitHub Marketplace
- docker/login-action: GitHub Action to login against a Docker registry
を利用しています。利用方法は、with
で
registry
にpublic.ecr.aws
username
にAWS アクセスキーID
password
にAWS シークレットアクセスキー
を指定すればいいだけです。
※ 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()
を使えばいいかと思います
こちらを参考にしました。まじで感謝です。
- GitHub ActionsでSlack通知をcurlで – Qiita
- Slack API attachmentsチートシート – Qiita
- ステータスによるステップの制御 – GitHub Actions | nju33
これで、何かしらの修正(Dockerfileとか)などでimageを作成/更新した後は、タグをつけてリポジトリにpushすれば、ECR publicにpushされるようになりました。めでたしめでたし。
おわりに
はっぴーはろうぃーん🎃👻
※ 2021年10月31日 PM11:45 に公開されています