概要
Dockerで構築したJenkinsで Dockerイメージを作成して Artifact RegistryにPushするまでの作業手順を記録します。
- DockerでJenkinsを構築
- Azure ADを利用したJenkinsログインを設定
- Jenkinsで Spring Boot アプリケーション(jar)を動かすためのDockerイメージをビルド
- 作成したDockerイメージを GCPの Atifact RegistoryにPush
前提
- Dockerを利用しているのは、社内システムとしてのデプロイ先としてDockerを利用しているため
- Jenkinsを利用しているのは、社内システムデプロイ先が(IPアドレス制限などの制約)があるため、自前のCI環境を作る必要があったため
背景
Spring Boot で開発したWebアプリケーションをDocker化してクラウド環境にデプロイしたいと考え、Dockerレジストリに登録するまでの作業を行いました。
DockerでJenkinsを構築
用意するもの
- Dockerfile
- docker-comopse.yml
Dockerfile
Dockerをインストールしておく、Dockerサービス自体はホストマシンと共有する
FROM jenkins/jenkins:lts
USER root
RUN curl -fsSL https://get.docker.com -o get-docker.sh && \
sh ./get-docker.sh
※参考
https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script
docker-compose.yml
ポイントは以下
- 上記で作成したDockerファイルを利用
- ホスト側の docker.sock をコンテナ側にマウント
version: '2.0'
services:
jenkins:
build:
context: .
dockerfile: Dockerfile
restart: always
ports:
- '8080:8080'
environment:
TZ: Asia/Tokyo
volumes:
- jenkins-volume:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
volumes:
jenkins-volume:
jenkins 起動
Dockerfile及び、docker-compose.ymlがあるディレクトリで以下コマンドを実行
$ docker-compose up -d .
JenkinsでAzureADを利用したJenkinsログイン環境
社内アカウントはMicrosoft365を利用しているので、AzureADでのログイン設定を実施
AzureADでアプリ登録
- 以下URLから新規登録を行う
https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade - アプリケーション形式は 「Web」
- 「リダイレクト URI」は以下を設定
https://{Jenkinsサーバドメイン}/securityRealm/finishLogin
- 「フロントチャネルのログアウト URL」は以下を設定
https://{Jenkinsサーバドメイン}/securityRealm/OicLogout」
- 「証明書とシークレット」から新しいクライアントシークレットを作成し手元にメモしておく
Jenkinsでプラグイン登録及び設定
- Microsoft Entra ID (previously Azure AD) Plugin をインストール
- 「Jenkinsの管理」-> 「Security」に移動
- ユーザー情報を「Azure Active Directory」を選択
- Client ID、Client Secret、Tenant にアプリ登録及びクライアントシークレット生成で取得した値を設定する。
Jenkinsで Spring Boot アプリケーション(jar)を動かすためのDockerイメージをビルド
- ビルド用Dockerfile
FROM eclipse-temurin:17-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
- JenkinsでPipelineジョブを作成
- 下記 Pipelineジョブを作成(一部抜粋)
stage('before build') {
steps{
script {
// build.gradle のバージョンを取得
env.APP_VERSION = sh(script: "cat build.gradle | grep \"version = \" | sed \"s/'//g\" | awk '{print \$3}'", returnStdout: true).trim()
}
}
}
stage('build jar') {
steps {
sh './gradlew build'
}
}
stage('build docker image') {
steps {
sh '''
docker build --build-arg JAR_FILE=/build/libs/app-${APP_VERSION}.jar \
-t {LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE}:${APP_VERSION} .
'''
}
}
作成したDockerイメージを GCPの Artifact RegistoryにPush
Artifact Registoryにリポジトリを作成
- 適当な「名前」を設定
- 形式は「Docker」を設定
- リージョンは適切に設定
- 他の設定はデフォルトにし「作成」を押下する
JenkinsからPushする際の認証用サービスアカウントを作成
- 適当な「サービスアカウント名」を設定
- ロールに「Artifact Registory リポジトリ管理者」を設定
- それ以外は変更せず作成
- 作成したサービスアカウント -> キー から新しい鍵を「JSON形式」で作成
Jenkinsにサービスアカウントで作成した鍵を登録する
- Jenkinsの管理 -> Credentialsに移動
- (global)Domainに対して Add Credentialsを行う
- 種類は「Secret file」を選択し、作成したJSON形式の鍵をアップロード
- ID、説明は適当に入力し作成
PipelineScriptでArtifact RepositoryへのPushを定義する
下記Pipeline Scriptを作成
stage('register docker image') {
steps {
withCredentials([file(credentialsId: '{設定したCredentialsID}', variable: 'AUTH_KEY_FILE')]) {
sh '''
# 認証
cat "$AUTH_KEY_FILE" | docker login -u _json_key --password-stdin https://{LOCATION}-docker.pkg.dev
# Push
docker push {LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE}:${APP_VERSION}
'''
}
}
}
stage('after build') {
steps {
sh '''
# PushしたDockerイメージを削除
docker images -q "{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE}" | xargs docker rmi -f
'''
}
}
感想
- JenkinsのログインをAzureADにすると全てそれになり、ローカルID/PASS認証が出来なくなるので困りそう
- pipelineの書き方について少し学習できた
- dockerイメージの運用(バージョンの付け方とか)とかどうするのが良いかあまり分かっていないので、要検討(latestとその他とか)
- APP_VERSIONでDockerイメージのタグを指定しているけど、バージョンはrelease時に設定するので、デバック用のイメージ作成とか考えると、コミットハッシュの方がよさそう。そこは使い分けなのか。