Amazon ECR(Elastic Container Registry)でのコンテナイメージの管理は、レジストリをクリーンでコスト効率の高い状態に保つために重要だ。時間が経つにつれて、未使用や非推奨のイメージが蓄積され、ストレージコストの増加や運用オーバーヘッドにつながる可能性がある。よくあるシナリオの一つは、特定のタグ付けパターンに従うイメージの削除だ。ここでは「9.x.x」形式(xは1桁以上の数字)のバージョンでタグ付けされたイメージが対象となる。

この記事では、ECRイメージのクリーンアップを自動化するために設計されたBashスクリプトを紹介する。このスクリプトはdry-runapplyの2つのメインモードを提供し、ニーズに基づいて削除をシミュレートまたは実行できる。


スクリプト概要

このBashスクリプトはAWS CLIとjq(軽量で柔軟なコマンドラインJSONプロセッサ)を活用して以下を行う:

  1. 全ECRリポジトリの一覧表示:
    アカウント内のすべての利用可能なECRリポジトリをAWSにクエリする。
  2. イメージとタグの取得:
    各リポジトリについて、イメージの詳細(イメージダイジェストとタグを含む)を一覧表示する。
  3. タグフィルタリングの適用:
    正規表現(^9\.[0-9]+\.[0-9]+$)を使用して、「9.x.x」形式(例: "9.0.1" や "9.12.3")に一致するタグを持つイメージを見つける。
  4. 動作モード:
    • Dry Run(--dry-run): スクリプトは削除されるイメージを一覧表示するだけで、リスクなくどのイメージが削除対象になるかを確認する機会を提供する。
    • Apply(--apply): 特定されたイメージを実際にリポジトリから削除する。
  5. 使用方法の情報:
    有効な引数なしでスクリプトが実行された場合、利用可能なオプションを説明するヘルプメッセージを出力する。

主な機能

1. 自動リポジトリ検出

  • 機能:
    スクリプトは手動入力やリポジトリ名のハードコーディングを必要とせず、利用可能なすべてのECRリポジトリを動的に取得する。
  • 利点:
    これにより、追加設定なしでアカウントのリポジトリリストの変更に対応でき、スクリプトのスケーラビリティと適応性が確保される。

2. 正規表現による柔軟なタグフィルタリング

  • 機能:
    9.で始まり、ピリオドで区切られたさらに2つの数字グループが続くバージョンタグに正規表現でマッチさせる。
  • 利点:
    正規表現ベースのアプローチにより、どのイメージをターゲットにすべきかを正確に制御できる。命名規則を維持し、特定の古くなった、または非推奨のバージョニングパターンに適合するイメージをクリーンアップできる。

3. デュアルモード動作(Dry-Run vs. Apply)

  • 機能:
    スクリプトはコマンドライン引数を受け取り、削除をシミュレートするか(--dry-run)、実際に実行するか(--apply)を選択する。
  • 利点:
    このデュアルモードアプローチは、破壊的なアクションを実行する前に影響を確認できる安全性を提供する。本番に近い環境で最初にスクリプトをテストする必要がある管理者にとって価値ある機能だ。

4. 堅牢なエラーハンドリングとストリクトモード

  • 機能:
    スクリプトはBashのset -euo pipefailを使用して厳格なエラーチェックを強制する。この設定により、エラー発生時、未設定変数の参照時、パイプライン内のいずれかのコマンドが失敗した場合にスクリプトの実行が停止する。
  • 利点:
    不完全な操作や予測不可能なスクリプト動作のリスクを最小化し、より信頼性の高い実行環境を促進する。

5. 明確な使用方法のドキュメント

  • 機能:
    誤った引数または引数なしで実行された場合、明確な使用方法の指示と各モードの説明を含むヘルプメッセージを表示する。
  • 利点:
    ユーザーエラーの削減に役立ち、スクリプトの操作方法を明確にする。経験の浅いユーザーにとってもアクセスしやすくなる。

長所と短所

長所

  • 安全性と予測可能性:
    dry-runモードの搭載により、管理者は削除を実行する前に変更をプレビューでき、偶発的なデータ損失のリスクを軽減する。
  • 自動検出:
    全リポジトリの自動クエリにより管理が簡素化され、包括的なクリーンアップが保証される。
  • 正規表現ベースのフィルタリング:
    タグフィルタリングのための堅牢な正規表現により、バージョンパターンに基づいて特定のイメージを簡単にターゲットできる。
  • シンプルさと拡張性:
    Bashで記述されているため、スクリプトは理解も修正も簡単だ。そのストレートな構造により、追加ニーズに合わせたさらなるカスタマイズが容易になる。
  • 堅牢なエラーハンドリング:
    スクリプトのエラーハンドリングメカニズム(set -euo pipefailの使用)は、予期しないエラーで実行を停止することで信頼性を高める。

短所

  • AWS CLIとjqへの依存:
    スクリプトはAWS CLIとjqの両方が正しくインストール・設定されている必要がある。これらのツールがプリインストールされていない環境では、追加のセットアップが必要だ。
  • 限定的な正規表現の柔軟性:
    現在の正規表現は「9.x.x」バージョンにマッチするよう特別に調整されている。バージョニングスキームが変更された場合、それに応じて正規表現を調整する必要があり、更新しない限りスクリプトの柔軟性は低くなる。
  • 過剰削除の可能性:
    イメージが複数の値でタグ付けされており、そのうちの1つが正規表現に一致する場合、削除コマンドはそのイメージに対して実行される。本番環境で削除モードを使用する際は特に注意が必要だ。
  • ロールバックメカニズムがない:
    一度イメージが削除されると(--applyモード)、復旧は簡単ではない。管理者は偶発的な削除に備えてバックアップやバージョン管理の手段を用意しておく必要がある。
  • 冗長なログ出力:
    スクリプトは処理された各イメージについてメッセージを表示するため、イメージ数が多い環境では圧倒される可能性がある。より簡潔なログアプローチに改善できる可能性がある。

ベストプラクティスと推奨事項

  1. まずステージング環境でテストする:
    常に--dry-runモードでステージング環境でスクリプトを実行し、ターゲットイメージを正しく特定できることを確認する。
  2. バックアップを実装する:
    変更をロールバックする必要があるリスクに備えて、イメージが適切にバックアップまたはバージョン管理されていることを確認する。
  3. ログを監視する:
    このスクリプトを定期的に(cron経由などで)実行する予定がある場合、出力ログをファイルにリダイレクトし、ログローテーションを実装することを検討する。
  4. 定期的な更新:
    ECRの使用状況やイメージタグ付け戦略が変更されるたびに、スクリプトをレビューしてテストする。
  5. 必要に応じて正規表現を微調整する:
    バージョニングシステムが進化したり、新しいタグ付け規則を導入したりした場合は、正規表現パターンを調整する。

スクリプト

#!/bin/bash
# This script processes all ECR repositories and their images, checks for image tags matching the pattern "9.x.x"
# (where x represents one or more digits), and then either lists (dry run) or deletes (apply) those images.
#
# Usage:
#   ./cleanup_ecr.sh --dry-run    # Lists images that would be deleted without performing deletion.
#   ./cleanup_ecr.sh --apply      # Deletes images with tags matching "9.x.x".
#   ./cleanup_ecr.sh              # Displays this help message.

set -euo pipefail

function usage() { echo “Usage: $0 [–dry-run | –apply]” echo "" echo " –dry-run List images that match the tag pattern ‘9.x.x’ without deleting them." echo " –apply Delete images that match the tag pattern ‘9.x.x’." }

Check command-line arguments

if [ “$#” -ne 1 ]; then usage exit 1 fi

MODE="$1" if [[ “$MODE” != “–dry-run” && “$MODE” != “–apply” ]]; then usage exit 1 fi

Define regex pattern for tags: “9.” followed by digit(s) a dot then digit(s)

REGEX="^9.[0-9]+.[0-9]+$"

echo “Mode: $MODE” echo “Fetching list of ECR repositories…”

Retrieve all repository names.

repositories=$(aws ecr describe-repositories –query ‘repositories[].repositoryName’ –output text)

Check if any repositories were returned.

if [ -z “$repositories” ]; then echo “No ECR repositories found.” exit 0 fi

Process each repository.

for repo in $repositories; do echo “——————————” echo “Processing repository: $repo”

# Retrieve image details: digest and tags.
images_json=$(aws ecr describe-images \
    --repository-name "$repo" \
    --query 'imageDetails[*].{Digest: imageDigest, Tags: imageTags}' \
    --output json)

# Determine the number of images in this repository.
image_count=$(echo "$images_json" | jq 'length')
if [ "$image_count" -eq 0 ]; then
    echo "  No images found in repository $repo."
    continue
fi

# Iterate over each image.
for (( i=0; i<image_count; i++ )); do
    image_digest=$(echo "$images_json" | jq -r ".[$i].Digest")
    # Extract tags; some images might have no tags.
    tags=$(echo "$images_json" | jq -r ".[$i].Tags[]" 2>/dev/null || true)

    if [ -z "$tags" ]; then
        continue
    fi
    
    # Loop through each tag.
    for tag in $tags; do
        if [[ $tag =~ $REGEX ]]; then
            echo "Match found - Repo: '$repo', Digest: '$image_digest', Tag: '$tag'"
            if [ "$MODE" == "--apply" ]; then
                echo "  Deleting image..."
                aws ecr batch-delete-image \
                    --repository-name "$repo" \
                    --image-ids imageDigest="$image_digest",imageTag="$tag"
            fi
        else
            echo "Skipping - Repo: '$repo', Digest: '$image_digest', Tag: '$tag'"
        fi
    done
done

done

echo “Process completed.”

結論

提供されたBashスクリプトは、指定されたタグパターンに一致するAmazon ECRイメージのクリーンアップを自動化するための堅牢で実用的なソリューションを提供する。シミュレーション(dry-run)と実行(apply)モードの明確な分離、自動リポジトリ検出、エラーハンドリングメカニズムにより、このスクリプトはコンテナイメージ管理のための強力なツールとなっている。

ただし、管理者は依存関係を認識し、特定のバージョニングスキームに合わせて正規表現フィルターを慎重に調整する必要がある。ステージング環境でのテストや削除ログの監視などのベストプラクティスに従うことで、このスクリプトはECRメンテナンスを大幅に効率化し、ストレージの肥大化を削減し、全体的な運用効率を向上させることができる。