アレについて記す

Spring Bootで作ったアプリのDockerizingとかを、Jenkinsさんにお願いしてみた

Posted on February 18, 2015 at 23:26 (JST)

Dockerのお勉強の一環として、Jenkinsで下記を実施してみました。

  1. Spring BootでWEBアプリからDockerイメージ作成
  2. 作成したDockerイメージをDocker HubへPUSH
  3. JenkinsのJob実行による公開サーバのDocker Pull&最新モジュールRUN
やったことを順に記載していきます。(長いです。。。)
なお、セキュリティ対策はしていません。気になる方は実施&Blog化をお願いします。

今回は今までBlogで取り上げてきたサンプルをもとに動作確認をしています。
ソースはGithubで公開しています。

【開発環境】

ローカル: Mac OSX10.9.5
CIサーバ(Vagrant1.7.2): CentOS6.5, Java8, Tomcat8, Docker1.4
公開サーバ(Vagrant1.7.2): CentOS6.5, Postgres9.4, Docker1.4

アプリの準備

GitHubに登録しているspring-boot-samplesをcloneした後、simple-mvc-appの部分だけを別プロジェクトとしてコピーして使用しました。
DBは本番(仮)ではPostgreSQLを使用し、開発環境はH2を使用するようになっています。
本番DB接続情報は環境変数から取得するようにしています。

[ application.yml(抜粋)]

spring:
  profle:
    active: dev
---
spring:
  profiles: dev
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:testdb;MODE=PostgreSQL
    username: sa
    password:
---
spring:
  profiles: prod
  datasource:
    driverClassName: org.postgresql.Driver
    url: ${DB_URL}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}


JenkinsでDockerイメージを作成するために必要なDockerfileをプロジェクトルート直下に配備しています。

[ Dockerfile ]

FROM naga/java8 #(1)
ADD ./build/libs/*.jar ./app.jar #(2)
EXPOSE 8080
CMD ["java", "-jar", "-Dspring.profiles.active=prod",  "./app.jar"] #(3)

(1): アプリに改修が入っても不変な範囲まではベースイメージとしてあらかじめ作成しておく。(詳細は後述)
(2): Gradleタスクのbuild成果物をイメージに取り込む。
(3): profileを起動引数に指定。

CIサーバーの準備

CIサーバの準備では下記を行いました。

  • Javaのインストール
  • Tomcatのインストール
  • GitBucketのインストール
  • Jenkinsのインストール
  • Dockerのインストール
  • Sshpassのインストール
  • Tomcatユーザー(Jenkins)がDockerを使用出来るよう設定
プロビジョニングはスクリプトを用いて自動化しました。
groovy-sshを用いてshを叩いているだけなので、興味がある方はコチラのソースをご覧ください。

Docker HUBの準備

Dockerイメージを公開サーバで使用するための準備として下記を行います。

  • Docker HUBのアカウント登録
  • JavaをインストールしたDockerイメージ作成とHUBへのPush
JavaイメージはCIサーバにログイン(vagrant ssh)して作成しました。
その際に使用したDockerファイルは下記となります。

[ Dockerfile ]

FROM centos
RUN yum install wget -y
RUN echo `wget --no-verbose --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u25-b17/jdk-8u25-linux-x64.rpm`
RUN rpm -ivh jdk-8u25-linux-x64.rpm
RUN rm -f jdk-8u25-linux-x64.rpm
ENV JAVA_HOME /usr/bin/java

アカウント登録やDockerの基本的な使用方法はドットインストールを参考に行いました。
作成後、Docker HUBのパブリックレポジトリに作成したイメージを登録しておきます。

公開サーバの準備

WEBアプリを配備するサーバーには、下記の準備を行います。

  • Dockerのインストール
  • PostgreSQLのインストール
  • WEBアプリ用のユーザとDBを作成
  • アプリ実行ユーザーを作成
  • 作成したユーザーの環境変数を設定
  • 作成したユーザーのホームディレクトリにアプリ起動用シェルを配備
こちらもプロビジョニングはスクリプトを用いて自動化しました。
興味がある方はコチラのソースをご覧ください。

アプリ起動用のシェルは下記となります。

[ run.sh ]

#!/bin/sh
docker pull naga/spboot-sample
docker ps -q | xargs docker kill
docker run -d -p 80:8080 -e DB_URL=$DB_URL -e DB_USERNAME=$DB_USERNAME -e DB_PASSWORD=$DB_PASSWORD naga/spboot-sample

起動している全てのDockerプロセスを止めて再起動しています。
もちろん手抜きです。

なお、環境変数はデプロイ用ユーザの~/.bashrcに登録しています。
~/.bash_profileだとJenkinsから起動しようとしたときに値がとれないので、注意が必要です。

GitBucketの設定

インストール直後のusername, passwordはどちらも root となっています。
アプリのプロジェクト登録とJenkinsへ変更を通知するためのWebHookの設定をします。
詳細は本投稿最下部の参照リンクをご覧ください。

Jenkinsの設定

Dockerイメージの作成&HUBへのPushを行うビルドJobと、公開サーバにsshログインして起動シェルを叩くデプロイJobを作成します。 事前準備として、下記のプラグインをインストールしてください。

  • Gradle plugin
  • GitBucket Plugin
  • Docker build publish Plugin
  • Workflow: Aggregator

【ビルドJobの設定】

まず、Docker build publish Pluginを使用するための設定を行います。
[Jenkinsの管理]>[システムの設定] 画面下の方にアカウント入力欄があります。

続いて、[新規ジョブ作成]>[フリースタイル・プロジェクトのビルド]でJobを作成します。
設定内容は図の通りです。


上記の設定でやってることは下記4点です。

  1. GitBucketのコミット検知し、Jobを起動
  2. Gradleのclean/buildタスクを実行しjarを作成
  3. 作成したjarを取り込んだDockerイメージを作成
  4. 作成したjarを保存しておく

【デプロイJobの設定】

JenkinsのWorkflowプラグインを使用します。
[新規ジョブ作成]>[Workflow]でJobを作成します。

今回は公開サーバにログインしてシェルを叩くだけの簡単なお仕事。
sh ‘sshpass -p hogehogehoge ssh -o StrictHostKeyChecking=no deployer@192.168.54.33 “sh run.sh”’
サーバにシェルを置かずに全部ここに設定も出来ますが、今回はシンプルにしています。


以上が今回やった設定でした。
コンテナが面白いと言われてる理由と、Spring Bootとの相性が良いと言われるのが実感出来ました。
「ポータビリティ」という視点で機能が他にも盛り込まれているようですので、今後もいろいろ試したいと思います。

Gradleの役割の大きさも注目したい点です。
Javaの世界のアレコレを今までだったらJenkinsさんにお願いしていましたが、
Gradleが自動テストからbuildまでやってくれることによりJobがだいぶすっきりしています。

最後に、今回は下記の記事を参考にさせてもらいました。ありがとうございます!!

以上です。