実際にデプロイするもの:アーティファクトと環境
あなたはラップトップでコードを書きます。それをリポジトリにプッシュします。誰かが「デプロイして」と言います。しかし、実際にデプロイされるのは何でしょうか?エディタに置いてある生のソースコード?そうではありません。ラップトップとサーバーの間で、重要な処理が行われます。コードはサーバーが実際に実行できる形に変換されます。その変換されたものをアーティファクトと呼びます。そして、それが実行される場所を環境と呼びます。
この2つの概念を理解すると、デリバリーに対する考え方が変わります。「コードを移動させる」という考え方から、「準備されたパッケージを適切な場所に出荷する」という考え方に変わります。
なぜ生のコードはサーバーで動かないのか
あなたがラップトップでPythonスクリプトを書き終えたと想像してください。Python 3.11がインストールされており、pipでインストールした多数のライブラリもあります。ラップトップには特定のバージョンのOpenSSL、特定のロケール設定、そして何ヶ月も前に設定して忘れてしまった環境変数があるかもしれません。
そのスクリプトを本番サーバーで実行したいとします。生の.pyファイルをそのままコピーしただけでは、サーバーはまったく同じPythonバージョン、まったく同じライブラリ、まったく同じシステム依存関係を持っている必要があります。何かが異なれば、予期しない方法でスクリプトが失敗する可能性があります。ライブラリのバージョンが違うかもしれません。サーバーにネイティブ拡張のコンパイラがないかもしれません。タイムゾーンの設定が原因で、午前2時にだけ発生する日付解析のバグが発生するかもしれません。
これが、生のソースコードを出荷しない理由です。出荷するのはアーティファクト、つまりアプリケーションの実行に必要なすべてを含む自己完結型のバンドルです。アーティファクトは管理された環境で一度だけビルドされ、その同じアーティファクトがどこにでもデプロイされます。再ビルドは不要で、「自分のマシンでは動く」という驚きもありません。
アーティファクトの姿
アーティファクトはビルドプロセスの出力です。その形は技術スタックによって異なります。
- Java: コンパイルされたバイトコードと依存関係を含むJARまたはWARファイル。
- Go: 外部依存関係のない単一のバイナリファイル。
- Python: すべてのライブラリを含むwheelファイルまたはzipバンドル。
- Node.js / フロントエンド: 最小化されたHTML、CSS、JavaScriptファイルのフォルダ。
- Docker: アプリケーションをランタイムとともにパッケージ化したコンテナイメージ。
重要な特性は、アーティファクトがすぐに実行できる状態であることです。コンパイル、依存関係の解決、環境のセットアップは不要です。サーバーに渡せば、サーバーがそれを実行します。それだけです。
アーティファクトの行き先:環境
アーティファクトができたら、それを実行する場所が必要です。その場所が環境です。環境は単なる異なるサーバーではありません。目的、データ、設定、リスク許容度が異なる、異なるコンテキストです。
開発環境
これはあなたのラップトップ、つまりローカルマシンです。ここでは自由に壊すことができます。実験的なブランチを試したり、データベースを削除したり、サービスを何度も再起動したりできます。他の人に影響はありません。データは偽物かサンプルです。設定はローカルサービスを指しています。目標は安定性ではなく、スピードと柔軟性です。
ステージング環境
ステージングは本番のレプリカであり、可能な限り本番に近づけたものです。同じハードウェアスペック、同じオペレーティングシステム、同じデータベースバージョン、同じネットワークトポロジー。データは匿名化された本番データか、実際の使用パターンを模倣した合成データかもしれません。
ステージングは、問題がユーザーに届く前に発見するために存在します。ここにアーティファクトをデプロイし、テストを実行し、手動チェックを行い、新しいバージョンが既存のインフラストラクチャで動作することを確認します。何かが壊れても、不便ではありますが、壊滅的ではありません。ユーザーに影響はありません。
本番環境
ここで実際のユーザーがアプリケーションとやり取りします。本番環境には実際のデータ、実際のトラフィック、そして何か問題が発生した場合の実際の影響があります。設定は慎重に管理されています。データベースの認証情報、APIキー、フィーチャーフラグ、コネクションプールはすべてライブ使用向けに設定されています。
本番環境へのデプロイにはより慎重さが必要です。段階的なロールアウト、カナリアデプロイ、ブルーグリーン戦略などを使用するかもしれません。監視、アラート、ロールバック計画が必要です。本番環境に到達するアーティファクトは、ステージングを通過したものと同じであるべきであり、別のビルドであってはなりません。
なぜ区別が重要なのか
多くのチームは環境を単なる「異なるサーバー」として扱います。どこにでも同じ方法、同じスクリプト、同じ注意レベルでデプロイします。それは間違いです。
各環境には異なる要件があります。
- データ: 開発では偽のデータを使用します。ステージングでは匿名化された本番データを使用するかもしれません。本番では実際のデータを使用します。ステージングを本番データベースに接続してはいけません。たとえ偶然でもです。
- 設定: APIエンドポイント、フィーチャーフラグ、リソース制限は環境ごとに異なります。開発で動作する設定ファイルが、ローカルデータベースを指していると本番でクラッシュする可能性があります。
- 障害に対する許容度: 開発ではいつでもサービスを再起動できます。本番では、再起動によってアクティブな接続が切断され、ユーザーをイライラさせる可能性があります。同じアクションでも、どこで行うかによって結果が異なります。
環境を異なるコンテキストとして扱うと、それに応じてデプロイプロセスを設計します。ステージングと本番で同じスクリプトを、違いを確認せずに実行することはありません。開発で動作するものが本番でも動作するとは想定しません。各ステップで検証します。
パイプラインがアーティファクトと環境をつなぐ
CI/CDパイプラインは、アーティファクトと環境の間の橋渡しです。アーティファクトを一度ビルドし、レジストリに保存し、環境間でプロモーションします。ステージングでテストに合格したのと同じアーティファクトが本番にデプロイされます。再ビルド、再コンパイル、「サーバーでこれをちょっと修正しよう」はありません。
コードから本番へのパスは次のようになります。
これがアーティファクト管理が重要である理由です。アーティファクトを保存し、バージョン管理し、どのアーティファクトがどの環境で実行されているかを追跡する場所が必要です。バグが報告されたとき、「それはバージョン1.4.3のアーティファクトで、コミットabc123からビルドされ、現在本番で実行されています」と言えるべきです。このトレーサビリティがなければ、デバッグは推測作業になります。
実践的なチェックリスト
次のデプロイの前に、これらを確認してください。
- アーティファクトは一度ビルドされ、レジストリに保存されていますか?
- 同じアーティファクトがステージングと本番にデプロイされていますか?
- 各環境には、アーティファクトとは別に独自の設定がありますか?
- 現在、各環境でどのバージョンのアーティファクトが実行されているかを追跡できますか?
- 再ビルドではなく、以前のアーティファクトを使用するロールバック計画がありますか?
具体的な要点
アーティファクトと環境は抽象的な概念ではありません。ソフトウェアをデリバリーするたびに実際に扱うものです。アーティファクトは出荷するものです。環境はそれが実行される場所です。これらを分離し、追跡可能にし、異なる環境にデプロイするからといってアーティファクトを再ビルドしてはいけません。本番サーバーは、テストに合格したのとまったく同じパッケージを実行するべきです。