はじめに
とある事情により、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.awsusernameにAWS アクセスキーIDpasswordに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 に公開されています

