1 ポイント 投稿者 GN⁺ 5 시간 전 | まだコメントはありません。 | WhatsAppで共有
  • コンテナレジストリは一見単純だが、誤ったタグ、プラットフォーム不一致、レイヤー欠落、実際には削除されないといった問題をデバッグするには、内部動作の原理を必ず理解する必要がある
  • レジストリの中核は コンテンツアドレス指定方式(content-addressable)の blob ストア で、すべてのレイヤー・設定ファイル・アーティファクトは digest をアドレスとして保存される
  • イメージの push は blob のアップロード後に manifest で束ねる順序 で進み、pull は manifest を先に受け取ってから blob を順にダウンロードする逆順の構造になっている
  • イメージ削除 は単なるアンタグだけでは完全に削除されず、ほかの manifest で共有中のレイヤーを先に確認したうえで、blob まで直接削除する必要がある
  • マルチプラットフォームイメージ は、既存の API エンドポイントをそのまま維持しつつ、image index(manifest list)という追加の間接レイヤーを 1 つ導入するだけで実現されている

Registry API 概要

  • 現代のコンテナレジストリの大半は OCI Distribution Specification を実装しており、この仕様はコンテンツ配布を標準化する API プロトコルを定義している
  • Registry API は実際には簡潔で理解しやすく、curl だけでも十分に直接操作できる

Blob のアップロードとダウンロード

  • レジストリは本質的に コンテンツアドレス指定 blob ストア であり、ファイルをローカルでハッシュ化した後、digest をアドレスとして使ってアップロードする
  • 最も単純なアップロード方式は Monolithic PUT 方式で、POST でセッションを初期化した後、PUT で blob を送信する 2 段階構造
    • 大容量ファイルには POST + PATCH + PUT のチャンクアップロード方式のほうが効率的だが、小さい blob であれば Monolithic PUT で十分
  • アップロード成功時には HTTP/2 201 Created レスポンスとともに、新しい blob の場所を指す Location ヘッダーが返される
  • ダウンロードは digest さえ分かれば GET /v2/<repo>/blobs/<digest> ですぐに実行できる

イメージ Push

  • イメージ push の手順: (1) 各 rootfs レイヤー の blob をアップロード → (2) image configuration blob をアップロード → (3) すべての digest を 1 つの JSON ドキュメントにまとめる manifest ファイルを push
  • manifest は PUT /v2/<repo>/manifests/<tag> エンドポイントにアップロードし、この時点でタグが作成される
  • 実際のクライアント(例: docker push)は blob アップロードを並列に実行するが、原理を理解するためには逐次処理でもよい
  • イメージディレクトリ構成例: config.json, layer-1.tar.gz, layer-2.tar.gz, manifest.json

タグ一覧の取得

  • GET /v2/<repo>/tags/list エンドポイントで、特定リポジトリの すべてのタグ一覧 を取得できる
  • この機能は docker CLI では公開されておらず、curl または craneregctl のようなツールでのみアクセスできる
    • craneregctl は同じエンドポイントを ls コマンドとしてラップしたもの

イメージ Pull

  • pull の手順は push の逆順: (1) GET /v2/<repo>/manifests/<tag>manifest を取得 → (2) manifest に記載された digest を使って すべての blob をダウンロード
  • 現代の manifest は rootfs レイヤーやイメージ設定に加え、Helm チャート、SBOM、出所証明(provenance attestation)、LLM の重み など任意のアーティファクトを blob として参照する汎用ストアとしても使われている

イメージ削除

  • イメージ削除は単純ではなく、タグの削除(アンタグ)だけでは manifest 自体は削除されない
  • 完全削除の手順:
    • (1) DELETE /v2/<repo>/manifests/<tag> でタグを削除
    • (2) manifest を digest で参照して、参照中のすべての blob を確認
    • (3) ほかの manifest で共有されていない blob だけ を選択的に削除
    • (4) DELETE /v2/<repo>/blobs/<manifest-digest> で manifest blob を削除
  • レジストリはコンテンツアドレス指定ストアであるため、同じ rootfs レイヤーを複数のイメージで共有でき、削除時にはそのレイヤーを参照している すべてのイメージに影響 する
  • 代替策として、すべてのタグを削除した後にレジストリの ガベージコレクション(garbage collection) 設定に依存する方法もあるが、公開レジストリでは常に有効とは限らない

マルチプラットフォームイメージ

  • マルチプラットフォームイメージは レジストリ API の構造変更なしに 実装されている — エンドポイントの追加・変更なしに既存 API をそのまま利用する
  • 構成方法:
    • 各単一プラットフォーム変種(amd64、arm64 など)を、それぞれ個別の manifest とともに digest ベースで先に push する
    • その後、image index(manifest list) と呼ばれる上位 manifest をタグ付きで push する
  • GET /v2/<repo>/manifests/<tag> を呼び出すと、単一プラットフォーム manifest または image index のいずれかが返され、呼び出し側は返却ドキュメントの content type で判別しなければならない
  • 結果として、マルチプラットフォーム対応は既存構造に 間接レイヤー 1 つと index ドキュメントのアップロード/ダウンロード手順 1 つ を追加しただけである

レジストリ API の保護

  • OCI Distribution Spec は認証方式を厳密には定義していないが、実際のレジストリの多くは HTTP Basic 認証 を使用している
  • 認証情報が平文で送信されるのを防ぐため、必ず HTTPS 上で運用する必要がある

まだコメントはありません。

まだコメントはありません。