kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

既存WebアプリケーションもJenkinsで自動デプロイしたい!(ビルド・デプロイ基礎編)

前回投稿の続きです。

前回は、Jenkinsで自動デプロイしてみたいシステムと、その問題点、自分なりの解決案の概要を書きました。
今回は、解決案のうち、ビルド・デプロイに関する基礎的な部分を、具体的に記述してみたいと思います。

今回の目標

次のような流れをJenkinsで自動化します。Subversionからソースを取得し、ビルドして、FTPでモジュールを配布し、Tomcatを再起動する。

ポイント

  • ファイルの配布は、AntのFTPタスクを使用する。
  • Tomcatの再起動は、TomcatのAntタスクを使う。

前提

  • Jenkinsは、開発環境(Windows)で起動する。
  • テスト環境のTomcatには、Webアプリケーション(古いモジュール状態)がデプロイ済みで動作する環境となっている。

プロジェクト構成

サンプルとして用意したWebアプリケーションのソースは、次のような構成です。特別なことはなく、Eclipseで動的Webプロジェクトで作成した構成です。

f:id:kurukuru-papa:20140113130621p:plain

手順(下準備)

ビルド

まず、ビルドを行うためのbuild.xmlを作成します。Eclipseで、プロジェクトを選択して、右クリックのメニューの「エクスポート」から、build.xmlを作成しました。多少、Tomcatのパス設定などを手直しして次のようになりました。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="build" name="Tomcat4.1Project01">
    <property environment="env"/>
    <property name="TOMCAT_HOME" value="../../apps/apache-tomcat-4.1.40"/>
    <property name="debuglevel" value="source,lines,vars"/>
    <property name="target" value="1.4"/>
    <property name="source" value="1.4"/>
    <path id="Apache Tomcat v4.1 [Apache Tomcat v4.1].libraryclasspath">
        <pathelement location="${TOMCAT_HOME}/common/lib/activation.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/ant-launcher.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/ant.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/commons-collections-3.2.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/commons-dbcp-1.2.2.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/commons-logging-api-1.1.1.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/commons-pool-1.4.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/jasper-compiler.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/jasper-runtime.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/jdbc2_0-stdext.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/jta.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/mail.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/naming-common.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/naming-factory.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/naming-resources.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/lib/servlet.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/endorsed/xercesImpl.jar"/>
        <pathelement location="${TOMCAT_HOME}/common/endorsed/xml-apis.jar"/>
    </path>
    <path id="Web App ライブラリー.libraryclasspath"/>
    <path id="EAR ライブラリー.libraryclasspath"/>
    <path id="Tomcat4.1Project01.classpath">
        <pathelement location="build/classes"/>
        <path refid="Apache Tomcat v4.1 [Apache Tomcat v4.1].libraryclasspath"/>
        <path refid="Web App ライブラリー.libraryclasspath"/>
        <path refid="EAR ライブラリー.libraryclasspath"/>
    </path>
    <target name="init">
        <mkdir dir="build/classes"/>
        <copy includeemptydirs="false" todir="build/classes">
            <fileset dir="src">
                <exclude name="**/*.launch"/>
                <exclude name="**/*.java"/>
            </fileset>
        </copy>
    </target>
    <target name="clean">
        <delete dir="build/classes"/>
    </target>
    <target depends="clean" name="cleanall"/>
    <target depends="build-subprojects,build-project" name="build"/>
    <target name="build-subprojects"/>
    <target depends="init" name="build-project">
        <echo message="${ant.project.name}: ${ant.file}"/>
        <javac debug="true" debuglevel="${debuglevel}" destdir="build/classes" includeantruntime="false" source="${source}" target="${target}">
            <src path="src"/>
            <classpath refid="Tomcat4.1Project01.classpath"/>
        </javac>
    </target>
    <target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
</project>

コマンドラインから、次のように実行して、ビルドが行われることを確認しました。

ant

デプロイ用モジュール収集

テスト環境へ配布しやすいように、テスト環境の構成に合わせて、モジュールを集めることにしました。次のようにbuild.xmlに追記します。

    <target name="make-deploy-files">
        <mkdir dir="build/deploy"/>
        <copy todir="build/deploy">
            <fileset dir="WebContent"/>
        </copy>
        <copy todir="build/deploy/WEB-INF/classes">
            <fileset dir="build/classes"/>
        </copy>
    </target>

コマンドラインから、次のように実行して、処理が行われることを確認しました。

ant make-deploy-files

モジュール配布

上記処理で収集したモジュールを、テスト環境へFTPアップロードします。これもAntで実現することにしました。

AntのFTPタスクを使うためには、Apache Commons Netが必要となりますので、次のサイトから、「commons-net-3.3.jar」をダウンロードしました。

build.xmlに、次を追加しました。

    <property name="server" value="xxxxx"/>
    <property name="ftp_userid" value="xxxxx"/>
    <property name="ftp_password" value="xxxxx"/>

    <target name="deploy-ftp">
        <echo message="デプロイ先サーバ: ${server}"/>
        <ftp server="${server}" userid="${ftp_userid}" password="${ftp_password}" remotedir="webapps/${ant.project.name}" verbose="true">
            <fileset dir="build/deploy">
                <include name="**/*"/>
            </fileset>
        </ftp>
    </target>

コマンドラインから、次のように実行して、処理が行われることを確認しました。

ant -lib build_lib\commons-net-3.3.jar deploy-ftp

Tomcat再起動

今回知ったのですが、Tomcatには、AntからTomcatを再起動するためのライブラリが用意されているのですね。さっそく使うことにしました。

次の記述をbuild.xmlに追加しました。

    <property name="tomcat_ant_jar" value="${TOMCAT_HOME}/server/lib/catalina-ant.jar" />

    <!-- Configure the context path for this application -->
    <property name="path"     value="/${ant.project.name}"/>

    <!-- Configure properties to access the Manager application -->
    <property name="url"      value="http://${server}:8080/manager"/>
    <property name="username" value="xxxxx"/>
    <property name="password" value="xxxxx"/>

    <!-- Configure the custom Ant tasks for the Manager application -->
    <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="install"   classname="org.apache.catalina.ant.InstallTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="list"      classname="org.apache.catalina.ant.ListTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="remove"    classname="org.apache.catalina.ant.RemoveTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="start"     classname="org.apache.catalina.ant.StartTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask" classpath="${tomcat_ant_jar}"/>
    <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask" classpath="${tomcat_ant_jar}"/>

    <target name="tomcat-reload">
        <reload url="${url}" username="${username}" password="${password}" path="${path}"/>
    </target>

コマンドラインから、次のように実行して、処理が行われることを確認しました。

ant -lib build_lib\commons-net-3.3.jar tomcat-reload

FTPTomcat再起動をまとめて実施できるように、build.xmlを追記しました。

    <target name="deploy" depends="deploy-ftp,tomcat-reload"/>

プロジェクト構成

ここまでで、次のようなプロジェクト構成になりました。Subversionにコミットしておきます。

f:id:kurukuru-papa:20140113131116p:plain

手順(Jenkins)

ビルドジョブ

新規ジョブを追加して、上記で作成した処理を呼ぶことにします。ジョブの名前は「Tomcat4.1Project01_Build」とし、次のように設定を行いました。

ソースコード管理」では、次のように設定しました。特別なことは無いと思います。

f:id:kurukuru-papa:20140113131135g:plain

build.xmlを次のようにして呼び出すことにしました。Eclipse環境と、Jenkinsの環境では、Tomcatのパスが異なることを考慮してあります。

f:id:kurukuru-papa:20140113131157g:plain

成果物を保存します。テスト環境に配布するモジュールと、配布するためのbuild.xmlなどを含んでいます。

f:id:kurukuru-papa:20140113131217g:plain

ジョブを実行し、正常に動作することを確認しました。

デプロイジョブ

新規ジョブを追加して、上記で作成した処理を呼ぶことにします。ジョブの名前は「Tomcat4.1Project01_Deploy」とし、次のように設定を行いました。

必要なファイルを、ビルドジョブから、コピーします。

f:id:kurukuru-papa:20140113131233g:plain

モジュール配布とTomcat再起動を行うためAntを呼び出します。FTPタスクを使用するため、ライブラリの設定を行っています。

f:id:kurukuru-papa:20140113131249g:plain

ジョブを実行し、正常に動作することを確認しました。

ジョブ起動設定

デプロイジョブ(Tomcat4.1Project01_Deploy)は、ビルドジョブ(Tomcat4.1Project01_Build)の終了後に起動されるように「ビルド・トリガ」を設定します。これで、ビルドジョブのジョブ実行をワンクリックするだけで、最新ソースのチェックアウトから、ビルド、デプロイまで自動化できました。

さらに、ビルドジョブの「ビルド・トリガ」でSubversionを監視するようにすれば、ワンクリックも不要となり、完全自動化もできますね。

今回作成したファイル

上記で記述したファイル類は、次の場所に置いておきました。興味があればご覧ください。

動作確認環境