Dev Study
AWSサービスの内部原理 コース

78. ECRは内容のハッシュで引く倉庫である — タグは動く名札、ダイジェストは動かない指紋

ECRのなかで、なぜ「タグは動く名札」で「ダイジェストは動かない指紋」になるのか、イメージの指し方が2通りある理由を図で追っていきます。

① レジストリ ⊃ リポジトリ ⊃ イメージ — 3階層の入れ子

レジストリアカウント × リージョンごとの入口
{account}.dkr.ecr.{region}.amazonaws.com
その中に(⊃)
リポジトリ1アプリのイメージ置き場(例: my-api)
IAMリソースベースポリシーで保護
その中に(⊃)
イメージDocker / OCIイメージ
アーティファクト署名・SBOM・Helmチャート等
  • レジストリのURIは {aws_account_id}.dkr.ecr.{region}.amazonaws.com。アカウントIDとリージョンで一意に決まる入口。
  • ECRは「private repositories with resource-based permissions using AWS IAM」。リポジトリ単位でIAMのリソースベースポリシーを貼り、誰が push/pull できるかを縛る。
  • リポジトリにはDockerイメージ・OCIイメージ・OCI互換アーティファクト(署名・SBOM・Helmチャート・スキャン結果・アテステーション等)が入る。

ECRは「入口(レジストリ)→アプリ棚(リポジトリ)→中身(イメージ)」の入れ子。アクセス制御はリポジトリという棚の単位でIAMポリシーとして貼る。API Gateway編で見た「AWSリソースにはIAMのリソースベースポリシーで境界を引く」のと同じ構図。

② イメージの指し方は2通り — 名札とハッシュ

タグで引くregistry/repo:tag(例: my-api:latest)
人間用の「動く名札」= 貼り替えできる
ダイジェストで引くregistry/repo@sha256:f1d4ae3f...
マニフェストのSHA-256 =「動かない指紋」
どちらも同じ1つのイメージを指す
イメージマニフェスト+レイヤ群
内容が1ビット違えば sha256 の値も変わる
  • pull時の名前の形式は、タグ指定が {registry}/{repository}[:{tag}]、ダイジェスト指定が {registry}/{repository}[@{digest}]。
  • ダイジェストの実例は sha256:f1d4ae3f7261a72e98c6ebefe9985cf10a0ea5bd762585a43e0700ed99863807(ECR公式のサンプル)。
  • ダイジェスト=イメージマニフェスト(レイヤの一覧とメタデータ)のsha256ダイジェスト。ECRのAPI仕様が「The sha256 digest of the image manifest」と定義している。
  • 1つのイメージが latest と 2016.09 の複数タグを同時に持てる一方、ダイジェストは中身から一意に決まる。

タグは人間が読むための名札で、あとから別のイメージに貼り替えられる。ダイジェストは中身をハッシュした指紋なので、中身が変わらない限り同じ値・中身が変われば必ず別の値になる。

③ コンテンツアドレッシング — 内容そのものが住所になる

名前で引くmy-api:latest
内容で引くmy-api@sha256:aaaa...
今日 pull すると
中身 Alatest → A
中身 Asha256:aaaa... → A
別イメージが push された明日、もう一度 pull すると
中身 B指す先が変わった
⚠ 名前→中身の対応は動く
中身 A常に同じ中身
住所(ハッシュ)=中身で不動
  • ダイジェスト指定のpullは、ハッシュが同じである限り常に完全に同一のバイト列を取得する。ハッシュは内容から一方向に決まるため、値が一致=中身が一致。
  • これはDynamoDB編で見た「ハッシュは内容から一方向に決まる短い指紋」という性質が、そのままストレージの索引(住所)になっている実例。
  • 設計としてはGitのコミットハッシュと同一の発想:名前(ブランチ名/タグ)ではなく内容のハッシュでオブジェクトを引く。

コンテンツアドレッシングとは「名前でなく内容そのものを住所にする」こと。だから本番で再現性を担保したいときは、動くタグではなく動かないダイジェストで固定する。

④ タグの怖さへの対策 — イミュータブルタグ

MUTABLE既存タグへの push を許す
デフォルト。latest が上書きされうる
IMMUTABLE に切替
IMMUTABLE既存タグへの push を拒否
ImageTagAlreadyExistsException で弾く
例外を作りたいなら
除外つき不変IMMUTABLE_WITH_EXCLUSION
基本は不変、ワイルドカード指定のタグだけ上書き可(例: filter=latest)
  • リポジトリ作成時に何も指定しなければタグ可変性はデフォルトで MUTABLE(API仕様に「If this parameter is omitted, the default setting of MUTABLE will be used」と明記)。
  • 「After tag immutability is turned on, the ImageTagAlreadyExistsException error is returned if you push an image with a tag that is already in the repository.」
  • 「Tag immutability affects all tags. You cannot make some tags immutable while others aren't.」— IMMUTABLEは全タグ一律。
  • 現行ドキュメントでは除外フィルタが存在する:CLIで --image-tag-mutability IMMUTABLE_WITH_EXCLUSION --image-tag-mutability-exclusion-filters filterType=WILDCARD,filter={filter-text}。逆にMUTABLEをベースに一部タグだけ不変化する MUTABLE_WITH_EXCLUSION(コンソールの「Mutable tag exclusion」)も用意されている。除外フィルタは1リポジトリあたり最大5個。

タグは動く名札ゆえ、latest は静かに別イメージへ貼り替わりうる。リポジトリをIMMUTABLEにすれば既存タグへの再pushを例外で弾き、名札を釘で打ち付けられる。前レッスンの「不変性」を、1レコードでなく運用ルール(リポジトリ設定)にまで広げた話。

⑤ 認証の両替 — IAMをDockerが話せる言葉に翻訳する

Docker CLIIAM(SigV4)を話せない
IAMプリンシパルがSigV4署名で呼ぶ
GetAuthorizationTokenaws ecr get-login-password
権限を「両替」して返す
認可トークンユーザー名は固定で AWS・有効期限12時間
権限範囲 = 取得したIAMプリンシパルと同じ
docker login に渡す(Basic認証)
docker pull / pushが通る
  • 「The Docker CLI doesn't support native IAM authentication methods.」だからこの両替が要る。
  • 「retrieve a base64-encoded authorization token containing the username AWS and an encoded password」「valid for 12 hours」。
  • 「An authorization token's permission scope matches that of the IAM principal used to retrieve the authentication token.」— トークンの権限はIAMプリンシパルの権限のコピー。広くも狭くもならない。
  • 1行の内訳: aws ecr get-login-password --region {region} | docker login --username AWS --password-stdin {account}.dkr.ecr.{region}.amazonaws.com
  • HTTP APIでは Authorization: Basic $TOKEN として送る=Basic認証スキーム。

aws ecr get-login-password | docker login の1行は、IAM(SigV4)しか持たない自分を、Dockerが理解できるBasic認証トークン(ユーザー名AWS・12時間有効)に両替する処理。認証暗号編のSigV4と一時的認証情報の応用で、「プロトコルが違う相手には、IAMを相手の言葉へ翻訳して渡す」。トークンの権限は元のIAMと同じなので、翻訳しても権限は増えも減りもしない。

⑥ おまけ:ライフサイクルポリシー — 使われない指紋を規則で掃除する

溜まるイメージリポジトリに増え続ける
ルールを定義
ライフサイクルポリシー例: タグなしは N 日で削除 / 直近 K 世代だけ残す
適用前にルールをテストできる
規則に合致したら
不要イメージを自動削除
  • 「Lifecycle policies help with managing the lifecycle of the images in your repositories. You define rules that result in the cleaning up of unused images. You can test rules before applying them to your repository.」

ダイジェストで内容を貯め込む倉庫は放っておくと肥大するので、規則(ポリシー)で古い/未タグのイメージを自動削除する。S3編で見たライフサイクルの再登場で、対象がオブジェクトからコンテナイメージに変わっただけ。

公式ドキュメントで詳しく ↗