Azure Container Registry(以下、ACR)、掃除してますか?
気づいたらAzure Container Registry(以下、ACR)内に不要なイメージがたまっていることも。
実際、あるタグをつけてACRにpush、その後ソースを修正して同じタグでpush、また少し変えて同じタグでpush、push、push、、、ということやっていたら、タグのついていないイメージ(マニフェスト?)が大量になっていた*1。
なので今回はそんなタグのついていないイメージを削除してACRのお掃除を。
こういうことをやってたらしい
一回目のpush。
タグにlatest
を付ける。
マニフェストダイジェスト | タグ |
---|---|
sha256:012345... | latest |
ソースコードやDockerfileやらを修正して二回目のpush。
タグは同じくlatest
を使う。
マニフェストダイジェスト | タグ |
---|---|
sha256:012345... | - |
sha256:abcdef... | latest |
二回目のpushで追加されたイメージにlatest
タグが付く。
一方でもともとlatest
タグを持っていた一回目のpushで追加されたイメージは、タグは外れるだけでそのまま残る。
三回目のpush。
タグは同じく(ry
マニフェストダイジェスト | タグ |
---|---|
sha256:012345... | - |
sha256:abcdef... | - |
sha256:7890ab... | latest |
latest
タグは三回目にpushしたイメージにつく。
いままでpushしたイメージはタグが外れても全部残っている。
これを延々と繰り返し、タグなしイメージが大量に出来上がっていた。
コンテナーイメージを使う側(AKS, ACA, ACI, App Service, etc...)がタグを使ってイメージを指定する運用の場合には、タグが付いていないイメージは使われていないはずなので*2、削除していいはず。
なので、タグのないイメージを問答無用で削除する。
タグなしイメージを削除する
大体の流れはこのドキュメントに書いてある。
今回はタグなしのイメージだけを消したいので、そのやり方を以下に。
削除対象イメージのリストアップ
どのイメージにタグが付いているか、逆にタグがついていないかは az acr manifest list-metadata
でわかる。
例えば、ACR名が acrsample
、リポジトリ名が hello-world
なら、以下のコマンドで各イメージのメタデータが取れ、その中にtags
のフィールドがある場合はそのイメージについているタグが列挙される。
$ az acr manifest list-metadata --registry acrsample --name hello-world [ { "architecture": "amd64". : "digest": "sha256:012345...", : "tags": [ "latest", : ] }, : { } ]
逆に、タグなしイメージにはtags
フィールドがないので、これを使ってフィルターできる。
出力フォーマットはJSONなので、いったん全部出力してjq
でフィルターしてもいい。
けど、--query
オプションを使いこなすとカッコいいのでJMESPathにチャレンジ。
$ az acr manifest list-metadata --registry acrsample --name hello-world --query "[?tags == null].digest" --output tsv
--query
使ったついでにdigest
だけ持ってくると、タグなしイメージのマニフェストダイジェスト一覧の出来上がり。
イメージの削除
イメージの削除は az acr repository delete
。
オプション--image
が単数形のとおり、一つずつしか消せない。
せっかくマニフェストダイジェストの一覧を取ったけど、このイメージ削除のコマンドをスクリプトでループさせるしかなさそう。
シェルスクリプトならこんな感じになるはず。
#!/bin/bash REGISTRY="acrsample" REPOSITORY="hello-world" UNTAGGED_DIGESTS=($(az acr manifest list-metadata --registry "${REGISTRY}" --name "${REPOSITORY}" --query "[?tags == null].digest" --output tsv)) for digest in "${UNTAGGED_DIGESTS[@]}" ; do az acr repository delete --name "${REGISTRY}" --image "${REPOSITORY}@${digest}" --yes done
一応 az acr repository delete
の実行時には確認のプロンプトが出るけど、ここでは強気の--yes
オプションを付けているので注意。
あと--name
オプションの意味がレジストリになったりレポジトリになったりで多少わかりづらい。
「もっと簡単に消したいんだけど。。。」
acr-cli
というのを使うとできるらしい。
さっきのスクリプトと同様、ACR acrsample
内のリポジトリ hello-world
のタグなしイメージを消すならこれ一発。
$ acr purge --registry acrsample --filter "hello-world:*" --untagged
簡単だった。
ただacr purge
はまだプレビューらしい。
「自動で定期的に消してほしいんだけど。。。」
acr-cli
とACR Taskを組み合わせるとできるらしい。
ACR TaskはACRを参照とか操作できるエージェントに、スクリプト/コマンドを実行させる機能。
cron式で定期的なスケジュール指定も可能。
このACR Taskでさっきのacr purge
を実行させれば、定期的にタグなしのイメージを消すことができる。
具体的な設定はこのドキュメントに書かれているので割愛。
タグなしのイメージはあまり意識しずらいけど、
- ACRの容量は確実に使っている
- 付属ストレージの容量を超えると追加で課金される
- 古いイメージに脆弱性があると、Defender for Cloudから警告が上がってくる
とあまりいいことはないので、ACRのお掃除は忘れずに。