Jenkins CIでTestcontainersを使用する方法

ソフトウェアを頻繁に自信を持ってリリースするには、テストを自動化する機能を含む強力な継続的インテグレーションと継続的デリバリー (CI/CD) プロセスが必要です。 Jenkins は、このようなソフトウェアプロジェクトのリリースを容易にするオープンソースの自動化サーバーを提供しています。

この記事では、Docker と Testcontainers Cloud を使用して、Jenkins パイプラインでオープンソースの Testcontainers フレームワークに基づいてテストを実行する方法について説明します。 

Testcontainers jenkins 2400x1260 1

Jenkinsは、コード変更のビルド、テスト、デプロイを自動化することで開発プロセスを合理化し、DevOpsエコシステムで広く採用されています。 膨大な数のプラグインをサポートし、さまざまなツールやテクノロジーとの統合を可能にし、特定のプロジェクト要件を満たすように高度にカスタマイズできます。

Testcontainers は、開発およびテストのユース ケース用に使い捨てのオンデマンド コンテナーをプロビジョニングするためのオープン ソース フレームワークです。 Testcontainersを使用すると、データベース、メッセージブローカー、Webブラウザー、またはDockerコンテナで実行できるほぼすべてのものを簡単に操作できます。

Testcontainers は、Java、Go、.NET、Node.js、 Pythonなど。 この記事では、Jenkins パイプラインで Testcontainers を使用して Java Spring Boot アプリケーション (testcontainers-showcase) をテストする方法について説明します。 リポジトリを GitHub アカウントにフォークしてください。 Testcontainers ベースのテストを実行するには、Docker などの Testcontainers がサポートするコンテナー ランタイムをエージェントで使用できる必要があります。

手記: Jenkins CI サーバーは主に Linux マシンで実行されるため、次の構成は Linux マシンでのみテストされています。

JenkinsエージェントとしてのDockerコンテナ

動的なDockerコンテナベースのエージェントを使用する方法を見てみましょう。 Dockerコンテナをエージェントとして使用できるようにするには、 Docker Pipeline プラグインをインストールします

次に、次の内容でプロジェクトのルートに名前 Jenkinsfile のファイルを作成しましょう。

pipeline {
   agent {
       docker {
             image 'eclipse-temurin:17.0.9_9-jdk-jammy'
             args '--network host -u root -v /var/run/docker.sock:/var/run/docker.sock'
       }
 }

   triggers { pollSCM 'H/2 * * * *' } // poll every 2 mins

   stages {
       stage('Build and Test') {
           steps {
               sh './mvnw verify'
           }
       }
   }
}

ここでは、 eclipse-temurin:17.0.9_9-jdk-jammy このパイプラインのビルドを実行するためのエージェントとしての Docker コンテナー。 ホストのUnix Dockerソケットをrootユーザー権限を持つボリュームとしてマッピングし、エージェントからアクセスできるようにしていますが、これはセキュリティ上のリスクとなる可能性があります。

を追加し Jenkinsfile 、変更をGitリポジトリにプッシュします。

次に、Jenkins ダッシュボードに移動し、 [新しい項目 ] を選択してパイプラインを作成します。 以下の手順に従います。

  • パイプライン名として「 testcontainers-showcase 」と入力します。
  • ジョブの種類として [パイプライン ] を選択します。
  • [ OK] を選択します。
  • [パイプライン] セクションで、次の操作を行います。
  • ビルドするブランチ: 分岐指定子 ('any' の場合は空白):*/main .
  • スクリプト パス: Jenkinsfile。
  • [ 保存] を選択します。
  • [Build Now ( 今すぐビルド )] を選択して、パイプラインを初めてトリガーします。

パイプラインは、リモートの Docker-in-Docker ベースの構成を使用して、コンテナーベースのエージェントで Testcontainers ベースのテストを正常に実行する必要があります。

Jenkins エージェントとしての Kubernetes ポッド

Kubernetes ポッドで Testcontainers ベースのテストを実行しているときに、Docker-in-Docker (DinD) コンテナーをサイドカーとして実行できます。 Kubernetes ポッドを Jenkins エージェントとして使用するには、 Kubernetes プラグインをインストールします。

これで、次のように Kubernetes ポッドをエージェントとして使用して Jenkins パイプラインを作成できます。

def pod =
"""
apiVersion: v1
kind: Pod
metadata:
 labels:
   name: worker
spec:
 serviceAccountName: jenkins
 containers:
   - name: java17
     image: eclipse-temurin:17.0.9_9-jdk-jammy
     resources:
       requests:
         cpu: "1000m"
         memory: "2048Mi"
     imagePullPolicy: Always
     tty: true
     command: ["cat"]
   - name: dind
     image: docker:dind
     imagePullPolicy: Always
     tty: true
     env:
       - name: DOCKER_TLS_CERTDIR
         value: ""
     securityContext:
       privileged: true
"""

pipeline {
   agent {
       kubernetes {
           yaml pod
       }
   }
   environment {
       DOCKER_HOST = 'tcp://localhost:2375'
       DOCKER_TLS_VERIFY = 0
   }

   stages {
       stage('Build and Test') {
           steps {
               container('java17') {
                   script {
                       sh "./mvnw verify"
                   }
               }
           }
       }
   }
}

Docker-in-Dockerベースの構成を使用して、Docker環境をエージェントで使用できるようにすることもできますが、このセットアップでは構成の複雑さとセキュリティリスクも生じます。

  • ホストのDocker Unixソケット(Docker-out-of-Docker)をエージェントでボリュームマウントすることで、エージェントはホストのDockerエンジンに直接アクセスできます。
  • DooD アプローチのファイル共有を使用する場合、コンテナー化されたアプリと Docker エンジンは異なるコンテキストで動作するため、バインドマウントの使用は機能しません。 
  • Docker-in-Docker (DinD) アプローチでは、安全でない特権コンテナーを使用する必要があります。

Docker-in-Docker: Containerized CI Workflows プレゼンテーションを視聴して、Docker-in-Docker ベースの CI セットアップの課題について詳しく知ることができます。

そこで登場するのがTestcontainers Cloudで、Testcontainersベースのテストをよりシンプルかつ確実に実行しやすくします。 

Testcontainers Cloud を使用すると、エージェントで Docker デーモンを実行する必要さえありません。 コンテナーはオンデマンドのクラウド環境で実行されるため、ビルドに高 CPU/メモリを備えた強力な CI エージェントを使用する必要はありません。

最小限のセットアップでTestcontainers Cloudを使用し、Testcontainersベースのテストを実行する方法を見てみましょう。

Testcontainers クラウドベースのセットアップ

Testcontainers Cloud は、依存するサービスをクラウド上の Docker コンテナーとしてスピンアップし、テストをそれらのサービスに接続することで、Testcontainers ベースのテストを大規模に実行するのに役立ちます。

Testcontainers Cloud アカウントをまだお持ちでない場合は、次の手順でアカウントを作成し、サービス アカウント トークンを取得できます。

  1. Testcontainers Cloud アカウントにサインアップします
  2. ログインしたら、組織を作成します。
  3. Testcontainers Cloud ダッシュボードに移動し、サービスアカウントを生成します(図 1)。
新しいtestcontainerクラウドサービスアカウントを作成し、アクセストークンを取得するためのインターフェイスのスクリーンショット。
図 1: 新しい Testcontainers Cloud サービス アカウントを作成します。

Testcontainers Cloud を使用するには、環境変数として渡 TC_CLOUD_TOKEN して、軽量の testcontainers-cloud エージェントを起動する必要があります。

Jenkins TC_CLOUD_TOKEN では、次のように値をシークレットとして格納できます。

  • ダッシュボードから、 [Manage Jenkins](Jenkins の管理) を選択します。
  • [ セキュリティ] で [ 認証情報] を選択します。
  • 新しいドメインを作成するか、 システム ドメインを使用できます。
  • [グローバル資格情報] で、 [資格情報の追加] を選択します。
  • [シークレット テキスト] として [種類] を選択します。
  • [シークレット ] に値を入力します TC_CLOUD_TOKEN 。
  • IDとして入力しますtc-cloud-token-secret-id
  • [作成] を選択します

次に、次のように更新 Jenkinsfile できます。

pipeline {
   agent {
       docker {
             image 'eclipse-temurin:17.0.9_9-jdk-jammy'
       }
 }

   triggers { pollSCM 'H/2 * * * *' }

   stages {

       stage('TCC SetUp') {
     environment {
      	 TC_CLOUD_TOKEN = credentials('tc-cloud-token-secret-id')
           }
           steps {
               sh "curl -fsSL https://get.testcontainers.cloud/bash | sh"
           }
       }

       stage('Build and Test') {
           steps {
               sh './mvnw verify'
           }
       }
   }
}

作成した認証情報の値tc-cloud-token-secret-idを使用して環境変数を設定しTC_CLOUD_TOKEN、テストを実行する前にTestcontainers Cloudエージェントを起動しました。

これで、更新された Jenkinsfileをコミットしてプッシュすると、パイプラインは Testcontainers Cloud を使用してテストを実行します。 Testcontainers ベースのテストが既定の Docker デーモンではなく Testcontainers Cloud を使用していることを示す、次のようなログ ステートメントが表示されます。

14:45:25.748 [testcontainers-lifecycle-0] INFO  org.testcontainers.DockerClientFactory - Connected to docker: 
  Server Version: 78+testcontainerscloud (via Testcontainers Desktop 1.5.5)
  API Version: 1.43
  Operating System: Ubuntu 20.04 LTS
  Total Memory: 7407 MB

また、Testcontainers Cloud の Turbo モードを、並列実行機能を備えたビルド ツールと組み合わせて活用することで、テストをさらに高速に実行することもできます。

Maven の場合、システムプロパティを使用して -DforkCount=N 並列化の度合いを指定できます。 Gradle の場合、プロパティを使用して maxParallelForks 並列化の度合いを指定できます。

次のように、4つのフォーク Jenkinsfile を使用してテストの並列実行を有効にすることができます。

stage('Build and Test') {
      steps {
           sh './mvnw verify -DforkCount=4' 
      }
}

詳細については、 ターボ モードでのテストの並列化に関する記事を参照してください。

結論

この記事では、Docker-out-of-DockerおよびDocker-in-Dockerベースの構成で、動的コンテナとKubernetesポッドをエージェントとして使用して、Jenkins CIでTestcontainersベースのテストを実行する方法について説明しました。 

次に、Testcontainers Cloud アカウントを作成し、Testcontainers Cloud を使用してテストを実行するようにパイプラインを構成する方法を学習しました。 また、Testcontainers Cloud Turbo モードとビルドツールの並列実行機能を組み合わせて活用する方法についても検討しました。 

例としてJavaプロジェクトを使用してこのセットアップを示しましたが、他の一般的な言語用のTestcontainerライブラリも存在し、同じ構成パターンに従って、Golang、.NET、Python、Node.jsなどのJenkins CIでTestcontainersベースのテストを実行できます。

Testcontainers Cloud の使用を開始する には、Web サイトで無料のアカウントを作成します

さらに詳しく