web-dev-qa-db-ja.com

Dockerイメージにテストを含める必要がありますか?

テストに関しては、2つのオプションが考えられます。

  1. テストとアプリケーションの両方を1つのイメージにまとめます。
  2. 画像にはアプリケーションコードのみを含めます。メインイメージの後にビルドし、それにいくつかのレイヤー(テストコード、依存関係など)を追加するテスト固有のコンテナーを作成します。

最初のオプションでは、コンテナーをテストして、テストされたとおりに出荷できます。明らかな欠点は、不要なコード(および潜在的にテストデータ)がイメージに含まれることです。

2番目のオプションでは、出荷されるイメージは、テストされるイメージとはまったく異なります。

どちらも悪い戦略のように見えます。 3番目に優れた戦略はありますか?

23
lfk

ビルド時のテストを実行する場合、推奨される方法は マルチステージビルド を使用することです。マルチステージDockerfilesを使用すると、ビルドとテストのすべての依存関係を備えた大きなステージを作成し、テストした正確なアーティファクトを別のステージにコピーして、小さなランタイムイメージを作成できます。

また、コンテナー内で実行するのではなく、外部インターフェースを使用して、複数のコンテナーのシステムレベルのテストが必要です。これらのテストにはサービス間の調整が含まれ、オーケストレーションへのアクセスなどのさまざまな依存関係が必要であり、ビルド時のテストほど完全ではなく、多くの場合完全に異なる言語で書かれているため、個別のDockerから実行することは大きな問題ではありませんシステムテスト専用のコンテナ。

11
Karl Bielefeldt

あなたが言ったように、3番目の方法があります。開発、テスト、展開を混同していると思います。 SDLC全体を最初に見て、達成しようとしていることを理解することをお勧めします。これは大きなトピックですが、要約するために最善を尽くします。

TL; DR;

つまり、以下を分離する必要があります。

  • あなたのコード
  • アプリケーション構成、から
  • システム環境構成。

それぞれが互いに独立している必要があり、適切に:

  • バージョン管理
  • テスト済み
  • 展開可能

長いバージョン

最初に、コードと構成の(個別のセット)で構成されるアプリケーションがあります。これは、ビルド機能と意図的な機能の両方についてテストする必要があります。これは継続的インテグレーション(CI)と呼ばれます。オンラインとローカルの両方で、このサービスのプロバイダーは多数あります。たとえば、リポジトリにリンクし、コミットするたびにビルドとテストを行うクラウドプロバイダーの場合は CircleCI です。リポジトリがオンプレミスであり、クラウドプロバイダーを使用できない場合、 Jenkins のようなものは同等です。アプリケーションがかなり標準的なものである場合、CIサービスが使用できる既存のDockerイメージがある可能性があります。そうでない場合は、アプリケーションコードと設定をデプロイできるクラスタまたはクラスタを作成する必要があります。正しく構成すると、アプリケーションコードの品質に関する豊富な統計情報が得られます。

次に、アプリケーションの機能と正確さに満足したら、コードベースに特定のリリースに適切なタグを付ける必要があります。次に、このビルドをテスト環境にデプロイする必要があります。コードはCIでテストされたコードと同じになりますが(正しく実行されていればそうです)、構成が異なる場合があります。繰り返しますが、一部のCIプロバイダーはこのステップを提供できるため、パッケージ化されたアプリケーションと個別構成のデプロイメントをテストできます。この段階には、通常、ユーザー機能テスト(新機能の場合)と自動テスト(既知の機能の場合)が含まれます。リリースがこの段階を通過する場合、統合テストのリリース候補があります。別のDockerコンテナーから自動化テストを実行できます。アプリケーションによっては、アプリケーション自体と同じくらい大きくて手の込んだものになる可能性があります-実際、あります テストの取り組みがコーディングの取り組みに対して1:1であるといういくつかのメトリック =(私自身はこれについては不明ですが)。

最後から2番目のステップは、(システム)環境を本番環境のように構築することです。本番環境でDockerを使用している場合は、ここでセキュリティの強化、ネットワーク、サーバーの最適化などを検討します。Dockerイメージは、開発で使用したイメージに基づいている場合があります(そうするのが理想的です)が、スケーリングとセキュリティが変更される場合があります。 、 私の言ったように。これで、アプリケーションの機能テストが完了するはずです。これで、セキュリティとパフォーマンスへの関心が高まります。機能テストに従って、ここでのテストは他のDockerイメージから開発、デプロイ、実行できます。このステップは恐ろしく高価であり、そうすることはめったに行われなかったので、生産を再現する専用のハードウェアが必要でした。今日、これは完全に実行可能であり、ほとんどすべての規模の環境を要求に応じて立ち上がって破壊することができます。

最後に、統合テストの構成デルタ(IPアドレス、データベースURI、パスワードなど)のほんの一部の構成デルタで本番環境に対応できるリリースがあります。コードベースは、少なくとも3つの異なる環境でこれでテストされていますポイントとシステム構成の大部分は少なくとも一度。

9
avastmick

あなたはさまざまな種類のテストを混同していると思います。基本的に、あなたは自問する必要があります:ここでテスト中のユニットは何ですか?

開発者として作業しているときの最も一般的なシナリオは、作業しているコードの単体/統合テストを作成することです。この場合、そのコードはテスト対象のユニットです。これらのテストはローカルまたはCIで実行します。

新しいDockerイメージを構築すると、テストできる新しいユニットになります。この画像についてどのようなことをテストしますか?それが提供しているAPIは何ですか?それをどのようにテストしますか?

それがWebアプリケーションである場合、イメージに基づいてコンテナーを開始し、いくつかのHTTP要求を実行して、応答が期待どおりであることを確認できます。私が経験していると思う問題は、アプリケーションコードに結合されているテストフレームワークに非常に慣れていることです。開発中は問題ありませんが、今はドッカーイメージをテストしたいので、それを実行でき、アプリケーションコードに関連付けられていない新しい種類のテストフレームワークが必要です。

だから私はあなたが探している3番目の選択肢は次のとおりだと思います:

  • Dockerイメージをビルドする前に、ユニット/統合テストを実行します。
  • 配布するアプリケーションのみを含むDockerイメージをビルドします。
  • そのアプリケーションイメージの上に追加のレイヤーを追加する代わりに、特定のパラメーターを指定して実行し、期待される出力をアサートすることにより、それをそのままテストします。

したがって、CI/CDの手順は次のようになります。

開発環境のセットアップ->コードでテストを実行->最終イメージをビルド->イメージでテストを実行->イメージのデプロイ。

0
Lars Nyström