コンテナイメージの環境間プロモーション:タグよりもダイジェストが重要な理由
コンテナイメージのビルドが完了しました。ビルドパイプラインは正常に実行され、セキュリティスキャンも問題なし。イメージはレジストリに myapp:build-456 のようなタグで格納されています。さて、次はどうするべきでしょうか?
多くのチームは、セキュリティチェックを通過したらすぐに本番環境で使えると思い込んでいます。しかし、「このイメージに深刻な脆弱性はない」という状態と、「このイメージが実際のユーザーに安全に提供できる」という状態の間にはギャップがあります。このギャップを埋めるのがイメージプロモーションです。
イメージプロモーションとは、イメージをある環境から別の環境へ、制御された段階的な方法で移動するプロセスです。典型的な流れは、ビルドまたは開発環境から始まり、ステージング環境を経て、最終的に本番環境に到達します。各ステップは単なるファイルコピーではありません。検証、承認、そしてステージングでテストされたイメージとまったく同じものが本番環境にデプロイされるという保証が含まれます。
単純なタグ付けの限界
プロモーションを処理する最も単純な方法はタグを使うことです。ビルドが完了したら、イメージに myapp:build-456 とタグを付けてレジストリにプッシュします。次に、そのタグをステージングにデプロイします。QAチームがテストを実行します。すべてが合格したら、myapp:staging-passed や myapp:ready-for-production といった別のタグを追加します。
このアプローチは機能しますが、隠れたリスクがあります。タグは可変です。誰かが同じタグで新しいイメージをプッシュすると、タグを上書きできます。そうなると、ステージングで実行されているイメージと本番環境にプロモーションされるイメージが同じものではなくなる可能性があります。タグには staging-passed と書かれていても、実際のイメージは異なる可能性があるのです。
これがコンテナイメージのダイジェストが存在する理由です。ダイジェストはイメージコンテンツの暗号学的ハッシュです。不変です。2つのイメージが同じダイジェストを持つ場合、それらは最後の1バイトまで同一です。イメージをプロモーションするときは、タグではなくダイジェストで参照するべきです。タグは便利なラベルです。ダイジェストが真実です。
承認ゲート:人間の介入が必要な場面
本番環境へのイメージプロモーションには、ほとんどの場合、承認ゲートが必要です。承認ゲートとは、パイプライン内で誰かが明示的に同意を与えるまでイメージが先に進めないポイントです。承認する人はチームのポリシーによって異なります。テックリード、エンジニアリングマネージャー、QA担当者などが考えられます。重要なのは、本番環境へのプロモーションの決定は完全に自動化されていないということです。人間が責任を負います。
より厳格な承認ゲートを実装するチームもあります。例えば、イメージがステージングで一定時間以上、問題なく稼働していること、シミュレートされた本番トラフィックでテストされていること、セキュリティスキャン結果がセキュリティチームのメンバーによってレビューされていることなどが条件として挙げられます。これらの条件はすべて、イメージが本番環境に到達する前に前提条件として設定できます。
承認ゲートは官僚主義のためではありません。誰かが立ち止まって「これは本当に準備ができているのか?」と考える瞬間を作り出すためです。この振り返りの瞬間は、特に不適切なデプロイがビジネスに大きな影響を与える可能性があるアプリケーションにとって貴重です。
実際のプロモーションパイプライン
承認が得られると、プロモーションパイプラインが引き継ぎます。レジストリからダイジェストを使ってイメージをプルし、myapp:production-456 や myapp:1.2.3 のような本番用タグを追加し、本番サーバーまたはKubernetesクラスターにデプロイします。
次の図はこのパイプラインを視覚化したもので、重要なダイジェスト検証と手動承認ステップを強調しています。
ここで重要なのは、本番環境にデプロイされるイメージは、ステージングでテストされたイメージとまったく同じでなければならないということです。同じソースコードで再ビルドしたイメージでも、同じタグが付いた少し異なるイメージでもありません。同じダイジェストでなければなりません。これがダイジェストが譲れない理由です。イメージの違いによる「ステージングでは動いたのに本番では壊れた」という可能性を排除します。
具体的には、パイプラインでダイジェストを使ってイメージを再タグ付けし、プロモーションする方法は次のとおりです。
# ダイジェストでイメージをプル(正確なコンテンツを保証)
docker pull myregistry.io/myapp@sha256:abc123def456...
# ステージング用に再タグ付け
docker tag myregistry.io/myapp@sha256:abc123def456... myregistry.io/myapp:staging-passed
# 新しいタグをプッシュ(ダイジェストは変わらない)
docker push myregistry.io/myapp:staging-passed
# 後で、同じダイジェストを使って本番環境にプロモーション
docker pull myregistry.io/myapp@sha256:abc123def456...
docker tag myregistry.io/myapp@sha256:abc123def456... myregistry.io/myapp:production-1.2.3
docker push myregistry.io/myapp:production-1.2.3
Kubernetesを使用している場合は、デプロイメントを特定のダイジェストに固定できます。image: myapp:staging-passed の代わりに image: myapp@sha256:abc123... を使用します。これにより、誰かがタグを上書きしても、クラスターは意図したイメージを実行し続けることが保証されます。
プロモーションポリシーの定義
イメージプロモーションは技術的なプロセスであるだけでなく、プロセスとポリシーの問題でもあります。チームは以下を決定する必要があります。
- 本番環境へのプロモーションを承認できるのは誰か?
- イメージをプロモーションする前に、ステージングでどのくらいの時間実行する必要があるか?
- イメージが本番環境で失敗した場合のロールバック計画はあるか?
- パフォーマンスベンチマークやセキュリティの再レビューなど、追加のチェックが必要か?
答えはアプリケーションの影響によって異なります。トラフィックの少ない内部ツールであれば、開発者からの簡単な承認だけで十分かもしれません。数百万のトランザクションを処理する決済システムでは、複数の承認、ステージングでの浸漬期間、セキュリティ承認が必要になる可能性があります。
アプリケーションが重要であればあるほど、プロモーションプロセスは厳格であるべきです。しかし、小さなアプリケーションであっても、定義されたプロセスがあれば、アドホックな判断による本番インシデントを防ぐことができます。
イメージプロモーションの実践的チェックリスト
初めてイメージプロモーションを設定する場合の短いチェックリストです。
- 環境間でイメージを参照する際は、タグだけでなくダイジェストを使用する
- 本番環境へのプロモーションを承認できる人を定義する
- イメージがステージングで問題なく実行される最低時間を設定する
- プロモーションパイプラインがステージングから本番までまったく同じダイジェストを使用することを確認する
- プロモーションされたイメージが本番環境で失敗した場合の対応を文書化する
制御されたプロモーションの真の価値
イメージプロモーションは、デプロイプロセスに摩擦を加えることではありません。自信を生み出すことです。本番環境で実行されているイメージがすべてのテストに合格したイメージとまったく同じであるとわかっていれば、安心して眠れます。明確な承認プロセスがあれば、土壇場での判断による混乱を避けられます。ダイジェストを使用すれば、デプロイバグのクラス全体を排除できます。
次にビルドパイプラインが完了してイメージが生成されたとき、単に本番環境にプッシュしないでください。プロモーションしてください。ステージングで実績を積ませてください。人間に承認をもらってください。そして、何を実行しているのかを正確に把握した上で、自信を持ってデプロイしてください。