GitLabとJenkins連携入門|CI/CDパイプライン構築の第一歩
はじめに
現代のソフトウェア開発において、品質を維持しながら開発スピードを向上させることは、多くのチームにとって共通の課題です。この課題を解決するための強力なアプローチが「CI/CD (継続的インテグレーション/継続的デリバリー)」です。CI/CDは、開発プロセスを自動化し、コードの変更からテスト、リリースまでを迅速かつ確実に行うためのプラクティスです。
このCI/CDを実現するためのツールは数多く存在しますが、その中でも特に人気と実績を誇るのが、ソースコード管理プラットフォームの「GitLab」と、自動化サーバーの「Jenkins」です。
GitLabは、Gitリポジトリ管理を中核としながら、課題管理、コードレビュー、Wiki、そして独自のCI/CD機能(GitLab CI/CD)までを統合した、オールインワンのDevOpsプラットフォームです。
一方、Jenkinsは、CI/CDツールの草分け的存在であり、その歴史の長さから生まれる豊富なプラグインエコシステムと、高いカスタマイズ性が魅力です。あらゆるビルド、テスト、デプロイのタスクを自動化できる柔軟性を持っています。
なぜ、この二つを連携させるのでしょうか?
GitLabにもCI/CD機能はありますが、以下のような理由でJenkinsとの連携が選ばれることがあります。
- 既存のJenkins資産の活用: 長年Jenkinsを利用してきた組織では、すでに多くのジョブやパイプライン、プラグイン設定が蓄積されています。これらを捨てずに、ソースコード管理の中心をGitLabに移行したい場合に連携が有効です。
- 複雑なパイプラインへの対応: Jenkinsの豊富なプラグインと柔軟な設定により、特定のプログラミング言語、フレームワーク、あるいは特殊なデプロイ環境に依存する、非常に複雑なパイプラインを構築しやすい場合があります。
- 複数リポジトリをまたぐオーケストレーション: 複数のGitLabプロジェクト(リポジトリ)や、さらには他のバージョン管理システムと連携するような、大規模なワークフローをJenkinsで一元管理したいケースです。
この記事では、GitLabとJenkinsを連携させ、開発者がコードをGitLabにプッシュするたびに、Jenkinsが自動でソースコードを取得し、ビルドとテストを実行する、という基本的なCIパイプラインを構築する手順を、ゼロから詳細に解説します。
この記事で構築するパイプラインのゴール:
- 開発者がローカルで開発したコードをGitLabリポジトリにプッシュする。
- そのプッシュをGitLabが検知し、Webhookを通じてJenkinsに通知する。
- 通知を受け取ったJenkinsが、対象のGitLabリポジトリから最新のソースコードを自動で取得(チェックアウト)する。
- Jenkinsがソースコードのビルド(コンパイルなど)を実行する。
- Jenkinsが自動テスト(ユニットテストなど)を実行する。
- Jenkinsがビルドとテストの結果(成功/失敗)をGitLabに通知し、GitLabのコミット履歴やマージリクエスト画面に結果が表示される。
この一連の流れを自動化することで、CI/CDパイプライン構築の第一歩を踏み出します。この記事が、あなたの開発プロセスを自動化し、より効率的で品質の高いソフトウェア開発を実現するための一助となれば幸いです。
第1章: CI/CDの基礎知識
パイプライン構築に入る前に、CI/CDの基本的な概念を理解しておくことが重要です。これらの概念は、私たちがなぜこのパイプラインを構築するのか、その目的と価値を明確にしてくれます。
継続的インテグレーション (CI: Continuous Integration)
継続的インテグレーション(CI)とは、すべての開発者の作業コピーを、一日に数回、共有のメインライン(main
やdevelop
ブランチなど)にマージする開発プラクティスです。
CIの目的は、コードの統合時に発生する問題を早期に発見し、修正することです。複数の開発者が並行して作業を進めていると、それぞれの変更箇所が衝突(コンフリクト)したり、他の人の変更によって自分のコードが意図せず壊れてしまったりすることがあります。統合の頻度が低いほど、問題は大きくなり、解決に多くの時間と労力を要します。
CIを実践するために、以下のプロセスが自動化されます。
- 頻繁なコミットとプッシュ: 開発者は作業を小さな単位で完了させ、頻繁にリポジトリにプッシュします。
- 自動ビルド: コードがプッシュされるたびに、CIサーバー(今回はJenkins)が自動でソースコードを取得し、ビルド(コンパイルやパッケージング)を実行します。これにより、コードの文法エラーや依存関係の問題を即座に検出できます。
- 自動テスト: ビルドが成功した後、CIサーバーは自動でテストスイート(ユニットテスト、結合テストなど)を実行します。これにより、コードのロジックに潜むバグや、既存機能への悪影響(リグレッション)を早期に発見できます。
ビルドやテストが失敗した場合、チームは即座にフィードバックを受け取り、問題が大きくなる前に修正に取り掛かることができます。これにより、ソフトウェアの品質は常に高い水準に保たれます。
継続的デリバリー (CD: Continuous Delivery)
継続的デリバリー(CD)は、継続的インテグレーションをさらに一歩進めたプラクティスです。CIによってビルドとテストが完了したコードは、常に「リリース可能な状態」に保たれます。
継続的デリバリーでは、ビルドとテストに加えて、リリースに関わるプロセス(ステージング環境へのデプロイ、受け入れテストなど)も自動化します。最終的な本番環境へのデプロイのトリガーは、手動(例えば、プロダクトオーナーのボタンクリック)で行われますが、そこまでのプロセスはすべて自動化されているため、ビジネスの判断さえあれば、いつでも迅速かつ安全にリリースできる状態を維持します。
CIとの違い:
* CI: コードの統合とテストを自動化し、開発ブランチの健全性を保つことに主眼を置きます。
* 継続的デリバリー: CIのプロセスに加え、リリース準備までのプロセスを自動化し、いつでもリリースできる状態を保証します。
継続的デプロイメント (CD: Continuous Deployment)
継続的デプロイメント(CD)は、継続的デリバリーをさらに推し進めたものです。こちらもしばしば「CD」と略されますが、意味合いは異なります。
継続的デプロイメントでは、CIのビルドとテストをパスしたコード変更は、人手を介さずに自動的に本番環境までデプロイされます。ステージング環境へのデプロイや最終的な本番リリースも含め、パイプラインの全工程が完全に自動化されているのが特徴です。
このプラクティスを採用するには、非常に高度なテスト自動化と監視体制が不可欠ですが、実現できれば、ユーザーへの価値提供を最速で行うことができます。
CI/CDパイプラインとは
これらCI/CDのプラクティスを実現する一連の自動化されたプロセスのことを「CI/CDパイプライン」と呼びます。パイプラインは、ソースコードの変更から始まり、ユーザーに価値が届けられるまでの一連のステージで構成されます。
一般的なパイプラインのステージは以下のようになります。
- ソース (Source): 開発者がコードを変更し、GitLabのようなバージョン管理システムにプッシュします。これがパイプラインのトリガーとなります。
- ビルド (Build): ソースコードをコンパイルし、実行可能なファイルやパッケージ(JAR、Dockerイメージなど)を生成します。
- テスト (Test): ユニットテストや結合テストなどを実行し、コードの品質を検証します。静的コード解析などもこのステージで行われることがあります。
- デプロイ (Deploy): テストをパスしたアプリケーションを、ステージング環境や本番環境に配置します。
CI/CDパイプラインを導入することで、以下のような大きなメリットが得られます。
- 開発サイクルの短縮: 手作業によるビルドやデプロイの時間を削減し、より迅速に新機能をリリースできます。
- リスクの軽減: 小さな変更を頻繁にリリースすることで、一度の変更に伴うリスクを低減できます。問題が発生しても、原因の特定と修正が容易になります。
- 品質の向上: すべての変更に対して自動テストが実行されるため、バグが本番環境に到達する可能性を大幅に減らし、ソフトウェアの信頼性を高めます。
- 生産性の向上: 開発者は面倒な手作業から解放され、価値ある機能開発に集中できます。
今回構築するGitLabとJenkinsの連携は、この強力なCI/CDパイプラインの第一歩を築くためのものです。
第2章: 事前準備 – 環境構築
理論を学んだところで、次は実践です。パイプラインを構築するために必要な環境を整えましょう。
必要なツールとソフトウェア
このチュートリアルでは、以下のツールを使用します。環境はローカルマシンやクラウド上のVMなどを想定しています。
- GitLabアカウント: SaaS版のGitLab.comを利用します。無料で始めることができます。
- Jenkinsサーバー: Dockerを使ってローカルマシン上に構築します。Dockerを利用することで、環境構築が簡単かつクリーンになります。
- DockerおよびDocker Compose: Jenkinsサーバーをコンテナとして実行するために必要です。
- Gitクライアント: ローカルマシンでコードを編集し、GitLabにプッシュするために必要です。
- Java (JDK): サンプルアプリケーション(Java/Spring Boot)をビルドするために、Jenkinsコンテナ内にインストールしますが、ローカルでの開発にもあると便利です。
- Maven: Javaのビルドツールです。これもJenkinsコンテナ内に設定します。
GitLabの準備
まずは、パイプラインの起点となるGitLabの環境を準備します。
1. GitLab.comアカウントの作成とプロジェクト作成
- GitLab.comにアクセスし、アカウントを登録します(すでに持っている場合はサインイン)。
- サインイン後、新しいプロジェクトを作成します。「New project」->「Create blank project」を選択します。
- プロジェクト名(例:
jenkins-gitlab-sample
)、可視性レベル(Private
またはPublic
)などを設定し、「Create project」をクリックします。
2. SSHキーの登録
ローカルマシンからGitLabリポジトリに安全にアクセスするために、SSHキーを登録します。
- ローカルマシンでSSHキーペアを生成します(すでにある場合はスキップ)。
bash
ssh-keygen -t ed25519 -C "[email protected]" - 生成された公開鍵の内容をクリップボードにコピーします。
bash
# macOS
pbcopy < ~/.ssh/id_ed25519.pub
# Linux (xclipが必要)
xclip -selection clipboard < ~/.ssh/id_ed25519.pub
# Windows (Git Bash)
cat ~/.ssh/id_ed25519.pub | clip - GitLabの画面右上の自分のアイコンをクリックし、「Preferences」->「SSH Keys」に移動します。
- コピーした公開鍵を「Key」のテキストエリアに貼り付け、適当な「Title」を付けて「Add key」をクリックします。
3. アクセストークンの発行
JenkinsがGitLab APIと通信し、ビルドステータスを更新するためにアクセストークンが必要です。
- GitLabの画面右上の自分のアイコンをクリックし、「Preferences」->「Access Tokens」に移動します。
- 「Add new token」をクリックします。
- 「Token name」にわかりやすい名前(例:
jenkins-integration
)を入力します。 - 「Scopes」で
api
を選択します。これにより、API経由での全アクションが許可されます。 - 「Create personal access token」をクリックします。
- 重要: 表示されたアクセストークンを必ずコピーして安全な場所に保存してください。この画面を離れると二度と表示されません。
Jenkinsのインストールと初期設定
次に、CI/CDの中核を担うJenkinsサーバーをDockerで構築します。Dockerを使うことで、ホストマシンを汚さず、再現性の高い環境を簡単に作れます。
1. Docker Composeファイルの作成
作業ディレクトリを作成し、その中に docker-compose.yml
というファイルを作成します。
bash
mkdir jenkins-server
cd jenkins-server
touch docker-compose.yml
docker-compose.yml
に以下の内容を記述します。
“`yaml
version: ‘3.8’
services:
jenkins:
image: jenkins/jenkins:2.414.3-jdk17 # LTS版とJDKのバージョンを指定
container_name: jenkins
restart: unless-stopped
ports:
– “8080:8080” # JenkinsのWeb UI用ポート
– “50000:50000” # エージェント接続用ポート
volumes:
– jenkins_home:/var/jenkins_home # Jenkinsのデータを永続化
environment:
– JAVA_OPTS=-Djenkins.install.runSetupWizard=false # 初期設定ウィザードをスキップ(後で手動設定)
volumes:
jenkins_home:
“`
image
: 公式のJenkinsイメージを指定します。LTS(長期サポート)版で、JDK17が含まれているイメージを選択しています。ports
: ホストマシンのポートとコンテナのポートをマッピングします。8080
はWeb UI用です。volumes
:jenkins_home
という名前付きボリュームを作成し、Jenkinsのデータ(ジョブ設定、プラグインなど)をコンテナが再起動しても保持されるようにします。
2. Jenkinsコンテナの起動
docker-compose.yml
があるディレクトリで、以下のコマンドを実行します。
bash
docker-compose up -d
これにより、バックグラウンドでJenkinsコンテナが起動します。
3. Jenkinsの初期設定
- ブラウザで
http://localhost:8080
にアクセスします。 - 「Unlock Jenkins」という画面が表示されます。管理者パスワードを入力する必要があります。以下のコマンドでコンテナ内のファイルからパスワードを取得します。
bash
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword - 表示された長い文字列をコピーし、ブラウザの「Administrator password」フィールドに貼り付けて「Continue」をクリックします。
- 「Customize Jenkins」の画面で、「Install suggested plugins」を選択します。Git、Pipeline、Credentialsなど、基本的なプラグインが自動でインストールされます。
- プラグインのインストールが完了したら、「Create First Admin User」の画面が表示されます。管理者ユーザー名、パスワード、氏名、メールアドレスを入力して、「Save and Continue」をクリックします。
- 「Instance Configuration」の画面では、JenkinsのURLを確認し、問題なければ「Save and Finish」をクリックします。
- 「Jenkins is ready!」と表示されたら、「Start using Jenkins」をクリックしてダッシュボードに移動します。
これでJenkinsの基本的なセットアップは完了です。
4. 必要なプラグインの追加インストール
連携にはGitLab Plugin
が不可欠です。
- Jenkinsダッシュボードから、「Jenkinsの管理」->「Plugins」に移動します。
- 「Available plugins」タブを開きます。
- 検索ボックスに
GitLab
と入力し、「GitLab Plugin」にチェックを入れます。 - 「Install」ボタンをクリックしてインストールします。インストール完了後、Jenkinsを再起動すると確実です。
第3章: GitLabとJenkinsの連携設定
環境が整ったので、いよいよGitLabとJenkinsを繋ぎ込みます。双方向の通信設定が必要です。
- Jenkins -> GitLab: JenkinsがGitLabリポジトリにアクセスしたり、ビルドステータスを通知したりするための設定。
- GitLab -> Jenkins: GitLabでイベント(pushなど)が発生したときに、Jenkinsに通知するための設定 (Webhook)。
Jenkins側の設定
1. GitLab接続設定
Jenkinsに、GitLabサーバーの情報とAPI通信用のアクセストークンを登録します。
- Jenkinsダッシュボードから、「Jenkinsの管理」->「System」に移動します。
- ページを下にスクロールし、「GitLab」セクションを見つけます。
- 「Add GitLab Server」をクリックし、「GitLab」を選択します。
- 以下の項目を設定します。
- Connection name: わかりやすい名前(例:
GitLab.com
)を入力します。 - GitLab host URL:
https://gitlab.com
と入力します。 - Credentials: 「Add」->「Jenkins」をクリックして、新しい認証情報を追加します。
- Kind:
GitLab API token
を選択します。 - API token: 第2章で保存したGitLabのアクセストークンを貼り付けます。
- IDとDescription: わかりやすい名前(例:
gitlab-api-token
)を入力します。 - 「Add」をクリックして認証情報を保存します。
- Kind:
- 作成した認証情報がドロップダウンから選択されていることを確認します。
- Connection name: わかりやすい名前(例:
- 「Test Connection」ボタンをクリックします。「Success」と表示されれば、JenkinsからGitLab APIへの接続は成功です。
- ページ下部の「保存」をクリックします。
2. Gitリポジトリ用クレデンシャルの登録
JenkinsがGitLabリポジトリからソースコードをgit clone
するために、SSHキーを登録します。
-
Jenkinsが動作しているコンテナに、SSHキーペアを生成させるのが安全な方法です。
“`bash
# Jenkinsコンテナ内でbashを起動
docker exec -it -u root jenkins bash必要なツールをインストール
apt-get update && apt-get install -y openssh-client
jenkinsユーザーに切り替えてキーを生成
su jenkins
ssh-keygen -t ed25519 -C “jenkins@your-jenkins-server”パスフレーズは空のままEnterを押す
公開鍵を表示してコピー
cat ~/.ssh/id_ed25519.pub
exit # jenkinsユーザーを抜ける
exit # コンテナを抜ける
2. コピーした**公開鍵**を、GitLabプロジェクトの「Settings」->「Repository」->「Deploy Keys」セクションに追加します。
bash
* 適当な「Title」(例: `Jenkins Deploy Key`)を入力し、キーを貼り付けます。
* **「Write access allowed」にチェックを入れる**と、JenkinsからGitLabにタグをプッシュするなどの書き込み操作も可能になります(今回は不要ですが、将来的に便利です)。
* 「Add key」をクリックします。
3. 次に、Jenkinsに**秘密鍵**を登録します。
* コンテナから秘密鍵の内容を取得します。
docker exec -u jenkins jenkins cat /var/jenkins_home/.ssh/id_ed25519
``
—–BEGIN OPENSSH PRIVATE KEY—–
* 表示されたから始まる内容全体をコピーします。
(global)
* Jenkinsダッシュボードから、「Jenkinsの管理」->「Credentials」に移動します。
*ドメインをクリックし、「Add Credentials」を選択します。
SSH Username with private key
* 以下の項目を設定します。
* **Kind**:を選択します。
gitlab-ssh-key
* **ID**: わかりやすいID(例:)を入力します。
GitLab Deploy Key for jenkins-gitlab-sample
* **Description**: 説明(例:)を入力します。
git` と入力します(GitLabのSSH接続では通常このユーザー名が使われます)。
* **Username**:
* Private Key: 「Enter directly」を選択し、テキストエリアにコピーした秘密鍵を貼り付けます。
* Passphraseは空のままにします。
* 「Create」をクリックして保存します。
GitLab側の設定 (Webhook)
Webhookは、GitLab上で特定のイベントが発生した際に、指定したURL(この場合はJenkins)に対してHTTP POSTリクエストを送信する仕組みです。これにより、リアルタイムな連携が実現します。
- 連携したいGitLabプロジェクトのページに移動します。
- 左側のメニューから「Settings」->「Webhooks」を選択します。
-
以下の項目を設定します。
- URL: JenkinsがWebhookを受け取るためのURLを指定します。
http://<YOUR_JENKINS_PUBLIC_IP_OR_DOMAIN>:8080/project/<YOUR_JENKINS_JOB_NAME>
注意:
<YOUR_JENKINS_PUBLIC_IP_OR_DOMAIN>
は、GitLab.comからアクセス可能なJenkinsサーバーのパブリックIPアドレスまたはドメイン名に置き換える必要があります。ローカルのlocalhost
ではGitLab.comからアクセスできないため、ngrokなどのトンネリングツールを使うか、クラウド上にJenkinsを構築する必要があります。
また、<YOUR_JENKINS_JOB_NAME>
は、次の章で作成するJenkinsジョブの名前に置き換えます。先にジョブ名を決めておきましょう(例:gitlab-sample-freestyle
)。URL例:
http://123.45.67.89:8080/project/gitlab-sample-freestyle
もう一つの汎用的なURL
http://.../gitlab-webhook/
もありますが、今回はジョブ指定のURLを使います。
* Secret Token: セキュリティを強化するために、推測困難な文字列(パスワードなど)を設定します。このトークンは後でJenkinsジョブ側にも設定し、一致しないWebhookリクエストをJenkinsが無視するようにします。
* Trigger: Webhookを送信するきっかけとなるイベントを選択します。「Push events」にチェックを入れます。これで、git push
が行われるたびに通知が飛びます。
4. 「Add webhook」をクリックして保存します。 - URL: JenkinsがWebhookを受け取るためのURLを指定します。
これで双方向の連携設定が完了しました。Webhookリストの下部にある「Test」ボタンでテストできますが、まだJenkinsジョブが存在しないため、今はエラーになります。
第4章: シンプルなCIパイプラインの構築 (Freestyle Project)
いよいよ、最初のCIパイプラインを構築します。ここでは、Jenkinsで古くから使われている「Freestyle project」という形式でジョブを作成します。GUIベースで設定できるため、初心者にもわかりやすいのが特徴です。
目標: GitLabにpushされたJava (Spring Boot) アプリケーションを、Jenkinsが自動でビルドし、ユニットテストを実行する。
サンプルアプリケーションの準備
簡単なSpring Bootアプリケーションを用意し、GitLabリポジトリにプッシュします。
- Spring Initializr にアクセスします。
- 以下の設定でプロジェクトを生成します。
- Project:
Maven
- Language:
Java
- Spring Boot: 適当なバージョン(例: 3.x.x)
- Group:
com.example
- Artifact:
jenkins-gitlab-sample
- Packaging:
Jar
- Java:
17
- Dependencies:
Spring Web
- Project:
- 「GENERATE」をクリックし、zipファイルをダウンロードして解凍します。
-
このファイルを、先ほど作成したGitLabプロジェクトのローカルクローンディレクトリに配置します。
“`bash
GitLabからリポジトリをクローン
git clone [email protected]:
/jenkins-gitlab-sample.git
cd jenkins-gitlab-sampleダウンロードしたファイルを展開して、その中身をここにコピーする
.git ディレクトリと同じ階層に pom.xml や src ディレクトリが来るように配置
“`
-
変更をGitLabにプッシュします。
bash
git add .
git commit -m "Initial commit of Spring Boot application"
git push -u origin main
Jenkinsジョブの作成 (Freestyle project)
- Jenkinsダッシュボードに戻り、「新規ジョブ作成」をクリックします。
- 「エンター・ジョブ名」に、先ほどWebhookで指定したジョブ名(例:
gitlab-sample-freestyle
)を入力します。 - 「Freestyle project」を選択し、「OK」をクリックします。
ジョブの設定画面が開くので、各セクションを以下のように設定していきます。
一般 (General)
- 「GitLab Connection」のドロップダウンから、第3章で設定した
GitLab.com
を選択します。
ソースコード管理 (Source Code Management)
Git
を選択します。- Repository URL: GitLabプロジェクトのSSH URLを入力します(プロジェクトページの「Clone」ボタンからコピーできます)。例:
[email protected]:<your_username>/jenkins-gitlab-sample.git
- Credentials: ドロップダウンから、第3章で登録したSSHキーの認証情報(
gitlab-ssh-key
)を選択します。 - Branches to build: ビルド対象のブランチを指定します。
*/main
と入力すると、main
ブランチへのpushをトリガーにビルドが実行されます。
ビルド・トリガ (Build Triggers)
Build when a change is pushed to GitLab. GitLab webhook URL: http://...
というオプションにチェックを入れます。- 「Advanced…」ボタンをクリックして詳細設定を開きます。
- Secret token: 「Add」->「Jenkins」をクリックして新しい認証情報を追加します。
- Kind:
Secret text
を選択します。 - Secret: GitLabのWebhook設定で指定したSecret Tokenを貼り付けます。
- IDとDescription: わかりやすい名前(例:
gitlab-webhook-secret
)を入力します。 - 「Add」をクリックして保存し、ドロップダウンから作成したものを選択します。
- Kind:
- Allowed branches:
Filter branches by name
を選択し、main
と入力します。これにより、main
ブランチへのプッシュイベントのみがこのジョブをトリガーするようになります。
ビルド (Build)
ここで、ビルドとテストを実行するコマンドを定義します。
- 「ビルド手順の追加」をクリックし、「Invoke top-level Maven targets」を選択します。
- Maven Version:
(Default)
のままでOKです(JenkinsコンテナにMavenがプリインストールされていない場合は、Global Tool Configuration
で設定が必要です)。 - Goals:
clean install
と入力します。clean
: 以前のビルドで生成されたファイルを削除します。install
: コードをコンパイルし、テストを実行し、成果物(JARファイル)をローカルのMavenリポジトリにインストールします。Spring Bootのデフォルト設定では、install
フェーズで自動的にテストが実行されます。
ビルド後の処理 (Post-build Actions)
ビルド結果をGitLabに通知するための設定です。
- 「ビルド後の処理の追加」をクリックし、「Publish build status to GitLab」を選択します。
- これにより、Jenkinsのビルドが開始、成功、失敗した際に、そのステータスがGitLabの該当コミットに表示されるようになります。
最後に、ページ下部の「保存」をクリックしてジョブ設定を完了します。
パイプラインの実行と確認
すべての設定が完了しました。実際にパイプラインを動かしてみましょう。
- ローカルのサンプルアプリケーションのコードを少し変更します。例えば、
src/main/java/com/example/jenkinsgitlample/JenkinsGitlabSampleApplication.java
にコメントを追加するなど、簡単な変更で構いません。 - 変更をコミットし、GitLabにプッシュします。
bash
git add .
git commit -m "Test: Trigger Jenkins pipeline"
git push origin main - プッシュが完了すると、ほぼ即座にGitLabのWebhookが発火し、Jenkinsに通知が送られます。
- Jenkinsダッシュボードの「ビルド履歴」に、作成したジョブ(
gitlab-sample-freestyle
)が実行中(青い丸が点滅)または完了(青い丸は成功、赤い丸は失敗)として表示されることを確認します。 - ジョブ名をクリックし、特定のビルド(例:
#1
)をクリックすると、詳細画面に移動します。「Console Output」をクリックすると、ビルドとテストの実行ログをリアルタイムで確認できます。BUILD SUCCESS
と表示されていれば成功です。 - GitLabプロジェクトのページに戻り、「Code」->「Commits」に移動します。先ほどプッシュしたコミットの横に、緑色のチェックマーク(
passed
)が表示されていることを確認します。これが、Jenkinsから通知されたビルドステータスです。
おめでとうございます!これで、GitLabとJenkinsを連携させた基本的なCIパイプラインが完成しました。
第5章: JenkinsfileによるPipeline as Codeの実践
Freestyle projectはGUIで簡単に設定できますが、プロジェクトが複雑になるにつれて、設定の管理が煩雑になるという欠点があります。パイプラインの設定自体をコードとしてバージョン管理したい、という要求に応えるのが「Pipeline as Code」です。
Jenkinsでは、Jenkinsfile
という名前のテキストファイルにGroovy言語でパイプラインの処理を記述します。
Pipeline as Codeとは
パイプラインをコードとして定義することには、多くのメリットがあります。
- バージョン管理: パイプライン定義 (
Jenkinsfile
) をGitリポジトリでコードと一緒に管理できます。誰が、いつ、なぜパイプラインを変更したのかを追跡できます。 - 再利用性: 共通の処理をライブラリ化して、複数のパイプラインで共有できます。
- レビュー可能性: パイプラインの変更を、コードレビューのプロセス(マージリクエストなど)に乗せることができます。
- 耐久性: Jenkinsサーバーがダウンしても、パイプラインの定義はリポジトリに残っているため、簡単に復旧できます。
Jenkinsfileには2つの構文があります。
* Declarative Pipeline: より新しい、構造化された構文。シンプルで読みやすく、記述が簡単。推奨。
* Scripted Pipeline: より古く、柔軟な構文。Groovyスクリプトの能力を最大限に活用でき、非常に複雑なロジックを記述可能。
この記事では、初心者にもわかりやすいDeclarative Pipelineを使用します。
Jenkinsジョブの作成 (Pipeline)
まず、Jenkinsfileを読み込んで実行するPipeline
タイプのジョブを作成します。
- Jenkinsダッシュボードで「新規ジョブ作成」をクリックします。
- ジョブ名(例:
gitlab-sample-pipeline
)を入力し、Pipeline
を選択して「OK」をクリックします。 - ジョブ設定画面の「Pipeline」セクションを設定します。
- Definition: ドロップダウンから
Pipeline script from SCM
を選択します。これにより、JenkinsはGUI上のスクリプトではなく、ソースコード管理システム(SCM)内のJenkinsfileを読み込むようになります。 - SCM:
Git
を選択します。 - Repository URL: Freestyleの時と同じく、GitLabプロジェクトのSSH URLを入力します。
- Credentials: SSHキーの認証情報を選択します。
- Branches to build:
*/main
を指定します。 - Script Path:
Jenkinsfile
のままでOKです。これがリポジトリのルートディレクトリから探すファイル名になります。
- Definition: ドロップダウンから
- 「ビルド・トリガ」セクションもFreestyleの時と同様に、
Build when a change is pushed to GitLab
を設定し、Secret Tokenも指定します。 - 「保存」をクリックします。
Jenkinsfileの作成とリポジトリへの追加
次に、パイプラインの定義を記述するJenkinsfile
を、サンプルアプリケーションのリポジトリのルートディレクトリに作成します。
“`groovy
// Jenkinsfile
pipeline {
// 1. エージェントの指定
agent any // どのJenkinsエージェントでも実行可能
// 2. パイプラインのステージ定義
stages {
// "Build" ステージ
stage('Build') {
steps {
// 実行するステップ
echo 'Building the application...'
sh 'mvn clean package' // Mavenでビルドとパッケージングを実行
}
}
// "Test" ステージ
stage('Test') {
steps {
echo 'Testing the application...'
sh 'mvn test' // Mavenでテストを実行
}
}
}
// 3. パイプライン完了後の処理
post {
always {
// 常に実行される処理
echo 'Pipeline finished.'
// GitLabにビルドステータスを通知
updateGitlabCommitStatus name: 'build', state: 'success'
}
success {
// 成功時に実行される処理
echo 'Pipeline succeeded!'
}
failure {
// 失敗時に実行される処理
echo 'Pipeline failed!'
// GitLabにビルドステータスを通知(失敗)
updateGitlabCommitStatus name: 'build', state: 'failed'
}
}
}
“`
このJenkinsfile
の解説です。
pipeline { ... }
: Declarative Pipeline全体の定義ブロックです。agent any
: このパイプラインを、利用可能な任意のJenkinsエージェント(実行ノード)で実行することを示します。stages { ... }
: パイプラインの主要な処理を記述するブロックです。複数のstage
を持つことができます。stage('Build') { ... }
:Build
という名前のステージを定義します。JenkinsのUI上で、このステージ単位で進捗が表示されます。steps { ... }
: ステージ内で実行される具体的なコマンドや処理を記述します。echo '...'
: コンソールにメッセージを出力します。sh '...'
: シェルコマンドを実行します。ここではmvn
コマンドでビルドとテストを行っています。(clean package
はテストも内包しますが、ここではステージを分ける例としてtest
を別に実行しています)
post { ... }
:stages
ブロックの実行が完了した後に実行される処理を定義します。always
: 常に実行されます。パイプラインのクリーンアップなどに使います。success
: パイプラインが成功した場合にのみ実行されます。failure
: パイプラインが失敗した場合にのみ実行されます。updateGitlabCommitStatus
: GitLab Pluginが提供する便利なステップです。ビルドステータスをGitLabに通知します。state
にはpending
,running
,success
,failed
,canceled
が指定できます。
このJenkinsfile
をローカルリポジトリのルートに追加し、GitLabにプッシュします。
“`bash
ローカルリポジトリのルートで Jenkinsfile を作成・保存
git add Jenkinsfile
git commit -m “Add Jenkinsfile for Pipeline as Code”
git push origin main
“`
パイプラインの実行と確認
このプッシュをトリガーに、新しく作成したgitlab-sample-pipeline
ジョブが自動で実行されます。
- Jenkinsダッシュボードでジョブの実行を確認します。
- ジョブのページに移動すると、
Stage View
というUIが表示され、「Build」「Test」といったステージの進捗が視覚的にわかります。 - GitLabのコミット履歴を見ると、同様にビルドステータスが更新されているはずです。
これで、GUI設定から脱却し、コードによる宣言的なパイプライン管理が実現できました。パイプラインのロジックを変更したい場合は、もうJenkinsの画面を操作する必要はありません。Jenkinsfile
を修正してプッシュするだけで、パイプラインが更新されます。
第6章: 発展的なトピックとベストプラクティス
基本的なパイプラインが構築できたところで、より実践的なCI/CDに役立ついくつかの発展的なトピックとベストプラクティスを紹介します。
Dockerを使ったビルド環境の分離
agent any
は手軽ですが、JenkinsマスターノードにMavenやJDKなど、様々なツールをインストールする必要があり、環境が汚染されがちです。agent { docker { ... } }
を使うと、パイプラインの実行に必要な環境をDockerコンテナとして動的に起動し、その中でビルドを実行できます。
メリット:
* クリーンな環境: ビルドは毎回クリーンなコンテナ内で実行され、他のビルドからの影響を受けません。
* 再現性: Dockerイメージで環境が定義されているため、誰がどこで実行しても同じ結果が得られます。
* 管理の簡素化: Jenkinsノード本体に必要なのはDockerだけです。JDKやMavenなどのツールを管理する必要がなくなります。
Jenkinsfile
を以下のように修正します。
“`groovy
// Jenkinsfile using Docker agent
pipeline {
// Dockerイメージをエージェントとして指定
agent {
docker {
image ‘maven:3.8.5-openjdk-17’ // MavenとJDK 17がインストール済みの公式イメージ
args ‘-v $HOME/.m2:/root/.m2’ // Mavenの依存関係をキャッシュしてビルドを高速化
}
}
stages {
stage('Build & Test') {
steps {
echo 'Building and testing inside a Docker container...'
sh 'mvn clean install'
}
}
}
// (postブロックは同じなので省略)
}
“`
この設定により、パイプラインが実行されるたびにmaven:3.8.5-openjdk-17
イメージからコンテナが起動し、その中でmvn clean install
コマンドが実行されます。ビルドが終わるとコンテナは破棄されます。
成果物の管理 (Artifacts)
ビルドで生成されたJARファイルなどを、後でデプロイしたりダウンロードしたりできるように保存したい場合があります。archiveArtifacts
ステップを使います。
groovy
// ... (stagesブロック内)
stage('Archive Artifacts') {
steps {
echo 'Archiving the jar file...'
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
// ...
このステージを追加すると、ビルド完了後にtarget
ディレクトリにある.jar
ファイルがJenkinsに保存されます。ビルドの詳細ページから、保存された成果物をダウンロードできるようになります。fingerprint: true
は、ファイルの追跡を容易にするためのオプションです。
セキュリティに関する考慮事項
- Credentialsの適切な管理: パスワードやアクセストークン、秘密鍵などを
Jenkinsfile
に直接書き込んではいけません。必ずJenkinsのCredentials機能を使って管理し、パイプラインからはIDで参照するようにします。 - Secret Tokenの利用: Webhookには必ずSecret Tokenを設定し、意図しないリクエストからJenkinsを保護します。
- Jenkinsのユーザー権限管理: 本番運用では、Jenkinsの「Jenkinsの管理」->「Security」で、「Matrix-based security」などを有効にし、ユーザーやグループごとにジョブの閲覧、実行、設定変更などの権限を細かく設定することが推奨されます。
GitLab CI/CD vs Jenkins
最後に、GitLab CI/CDとJenkinsの比較について触れておきます。
特徴 | GitLab CI/CD | Jenkins |
---|---|---|
統合性 | GitLabに完全に統合。単一のUI/UX。 | 独立したツール。GitLabなどと連携が必要。 |
設定方法 | .gitlab-ci.yml (YAML) |
Jenkinsfile (Groovy) または GUI |
エコシステム | GitLabエコシステム内。機能はGitLabに依存。 | 非常に巨大なプラグインエコシステム。高い拡張性。 |
学習曲線 | YAMLベースで比較的習得しやすい。 | 多機能で柔軟な分、学習コストは高め。 |
適したケース | ・GitLab中心の開発フロー ・シンプルなCI/CD ・迅速な立ち上げ |
・既存のJenkins資産がある ・複雑/特殊なパイプライン ・複数VCSをまたぐ連携 |
GitLabとJenkinsの連携は、両者の「良いとこ取り」をするアプローチです。GitLabの優れたソースコード管理とコードレビュー機能(マージリクエスト)をトリガーとし、Jenkinsの強力な自動化エンジンと豊富なプラグインで複雑なパイプラインを実行するという、堅牢で柔軟な構成を組むことができます。
トラブルシューティング
- Webhookが届かない: GitLabのWebhookテストで404エラーが出る場合、URLのジョブ名が間違っているか、JenkinsのパブリックIP/ドメインが正しくない、ファイアウォールでポートがブロックされている、などの可能性があります。
- ビルドが失敗する: まずはJenkinsの「Console Output」を詳しく確認します。ローカルでは成功するのにJenkinsで失敗する場合、環境の違い(JDK/Mavenのバージョン、環境変数など)が原因であることが多いです。Dockerエージェントを使うと、この種の問題を減らすことができます。
- クレデンシャルエラー: Git cloneに失敗する場合は、SSHキーの登録(公開鍵をGitLab Deploy Keyに、秘密鍵をJenkins Credentialsに)が正しいか再確認してください。
おわりに
この記事では、CI/CDの基本概念から始まり、GitLabとJenkinsの環境構築、連携設定、そして実際にCIパイプラインを構築する手順までを詳細に解説しました。Freestyle projectによるGUIベースの簡単なジョブ作成から、Jenkinsfile
を使ったPipeline as Codeによる宣言的なパイプライン管理までを体験することで、両者の違いとそれぞれの利点を理解いただけたかと思います。
今回構築したのは、ビルドとテストを実行する「CI (継続的インテグレーション)」のパイプラインです。これはCI/CDの旅における、非常に重要で基礎となる第一歩です。
ここからさらに、以下のようなステップに進むことで、より本格的なDevOpsプラクティスへと発展させていくことができます。
- 継続的デリバリーの実装: ビルド成果物(JARファイルやDockerイメージ)を成果物リポジトリ(Artifactory, Nexus, Docker Hubなど)にプッシュするステージを追加する。
- デプロイの自動化: ステージング環境や本番環境へのデプロイをパイプラインに組み込む。
- インフラのコード化 (IaC): TerraformやAnsibleといったツールと連携し、インフラのプロビジョニングもパイプラインで自動化する。
- 高度なパイプライン戦略: マージリクエストが作成された時だけテストを実行したり、ブランチ戦略(Git-flowなど)に応じたパイプラインを構築したりする。
GitLabとJenkinsの連携は、開発プロセスを自動化し、チームの生産性とソフトウェアの品質を飛躍的に向上させるための強力な基盤となります。この記事で得た知識を元に、ぜひあなたのプロジェクトにCI/CDを導入し、その効果を実感してください。