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


19

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

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

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

2番目のオプションでは、出荷されるイメージはテストされるイメージとまったく同じではありません。

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


1
基本的に自分で答えました。両方とも悪い考えです。既にテスト済みの実行可能プロセスを、ニーズに合わせてサイズ設定およびカスタマイズされたコンテナーに出荷します。dev-dependenciesもsrcコードも必要ありません。本番環境ではリスクとみなされます。
ライヴ

1
コンテナ化の前にテストすると、環境はテストされず、コードのみがテストされます。すべてをテストするのではなく、出荷するものの一部のみをテストします。
lfk

回答:


10

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

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


1
だからそれはほとんどオプション2です-私は本番環境に非常に似ていますが、まったく同じではない環境/コンテナでテストを実行します。そうですか?
lfk

9

あなたが自分で言ったように、第三の方法があります。開発、テスト、展開を混同していると思います。あなたが何を達成しようとしているのかを理解するために、まずSDLC全体を全体として見ることを提案します。これは大きなトピックですが、要約するために最善を尽くします。

TL; DR;

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

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

それぞれが互いに独立しており、適切である必要があります。

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

長いバージョン

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

次に、アプリケーションの機能と正確性に満足したら、コードベースに特定のリリースのタグを適切に付ける必要があります。次に、このビルドをテスト環境に展開する必要があります。コードはCIでテストされたものと同じであることに注意してください(これを正しく行った場合はおそらくそうです)が、構成が異なる場合があります。繰り返しますが、一部のCIプロバイダーはこのステップを提供できるため、パッケージ化されたアプリケーションと個別の構成のデプロイメントをテストできます。通常、この段階には、ユーザー機能テスト(新機能用)と自動テスト(既知の機能用)が含まれます。リリースがこの段階に合格した場合、統合テストのリリース候補があります。別のDockerコンテナーから自動化テストを実行できますが、テストの努力を示すいくつかのメトリックは、コーディングの努力と1:1です(これについては自信がありませんが)。

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

最後に、統合テスト(IPアドレス、データベースURI、パスワードなど)からの構成デルタのわずかなセットのみで、本番稼働準備が整ったリリースが必要です。コードベースは、少なくとも3つの異なる環境でテストされています。ポイントとシステム構成の大部分を少なくとも1回。


つまり、CIはDockerfilesをまったくテストしませんか?たとえば、Dockerfileに依存関係が欠落している場合でも、テストは合格しますか?
lfk

1
どういたしまして。最初にコードをテストし、次にアプリの構成をテストしてから、システムをテストします。私が言っているのは、これらは個別の活動だということです。コンテナ化の素晴らしいところは、prodと同じ環境での開発の夢が非常に近いことです。しかし、強化により開発が難しくなります。
avastmick

0

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

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

新しいdockerイメージを作成すると、テスト可能な新しいユニットになります。このイメージについてどのようなことをテストしますか?提供しているAPIは何ですか?どのようにテストしますか?

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

だからあなたが探している3番目のオプションは次のとおりだと思います:

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

CI / CDの手順は次のとおりです。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.