DockerとJenkinsでJavaプロジェクトのコンパイル等してwarファイルのデプロイをする 

この記事の内容は古いのでJenkinsコンテナのプラグインのインストールに失敗します
→記事内で修正済

またgradleに修正した最新版を記事にしました
https://detofia.hateblo.jp/entry/2022/11/07/121559


仕事でインフラ担当者が用意したJenkinsやDockerを使っていますが、使っているだけであまり詳しくないので勉強しました。

事前にwarファイル作成対象のプロジェクトを、GitHubにpushしておきます。
https://github.com/jirentaicho/jenkinstest

devenvにDockerの設定ファイル等があります。


## やること


Dockerで以下のコンテナを作成します。

- Jenkins
- Tomcat


JenkinsはGitHub上のソースを取得して、GitHub上のJenkinsfileに従ってタスクを実行します。
行うタスクは以下の通りです。

- コンパイル
- テスト
- warファイルの出力
- Tomcatコンテナにデプロイ

デプロイには、Deploy to containerというJenkinsのプラグインを利用します。


## dockerコンテナの準備

Jenkins用のコンテナと、Tomcat用のコンテナを用意します。

#### 構成

フォルダ構成は以下のようにしました。
    
    devenv
    │  docker-compose.yml
    │
    ├─jenkins
    │  └─data
    └─tomcat
        Dockerfile

Dockerfileは以下のようになっています。

```dockerfile:Dockerfile
FROM tomcat:9.0
RUN apt-get update && apt-get install -y wget && apt-get install -y vim
```

docker-compose.ymlは以下のようになっています。

```yaml:docker-compose.yml
version: '3'
services: 
    tomcat:
        build:
            context: .
            dockerfile: ./tomcat/Dockerfile
        container_name: tomcat
        privileged: true
        ports:
            - "8012:8080"
        volumes:
            - "./tomcat/data:/var"
        tty: true
    jenkins:
        container_name: jenkins
        image: jenkins/jenkins:alpine
        ports:
            - "8888:8080"
        volumes: 
            - "./jenkins/data:/var/jenkins_home"
        tty: true
        links: 
            - tomcat
```

ここでjenkinsのimageを修正しています。
jenkins/jenkinsだとプラグインのインストールに失敗します


devenvフォルダで、以下のコマンドを打ってコンテナ立ち上げまで行います。

    docker-compose up -d


## Tomcatの設定

TomcatのWebアプリケーションマネージャの設定を行うことで、Jenkinsでのデプロイ作業が凄く簡単になりますので、Tomcatの設定を行います。

#### ロールとユーザーの追加

まずはtomcatコンテナに入ってtomcat-users.xmlを修正します。

    docker exec -it tomcat bash

    root@be401ef0872b:/usr/local/tomcat# find / -name tomcat-users.xml
    /usr/local/tomcat/conf/tomcat-users.xml
    root@be401ef0872b:/usr/local/tomcat# vim /usr/local/tomcat/conf/tomcat-users.xml

ファイルの最後のほうに以下のようなロールとユーザーを追加しました。
※jenkinsから実行するのでmanager-scriptを追加しています。

```xml:tomcat-users.xml
          <role rolename="manager-gui"/>
          <role rolename="admin-gui"/>
          <role rolename="manager-script"/>
          <user username="misaka" password="password" roles="manager-gui,admin-gui,manager-script"/>
</tomcat-users>
```    

#### managerフォルダのコピー

次にwebapps.distフォルダのmanagerをwebappsフォルダにコピーします。
というのも、初期状態ではwebappsフォルダが空っぽです。

    root@be401ef0872b:/usr/local/tomcat# cp -r webapps.dist/manager webapps
    root@be401ef0872b:/usr/local/tomcat#
    root@be401ef0872b:/usr/local/tomcat# ls
    BUILDING.txt     LICENSE  README.md      RUNNING.txt  conf  logs            temp     webapps.dist
    CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   native-jni-lib  webapps  work
    root@be401ef0872b:/usr/local/tomcat# cd webapps
    root@be401ef0872b:/usr/local/tomcat/webapps# ls
    manager

#### context.xmlの修正

許可するIPアドレスに関して修正します。今回はコメントアウトしてなんでも許可するようにしました。

    # find ./ -name context.xml
    ./conf/context.xml
    ./webapps/manager/META-INF/context.xml
    vim webapps/manager/META-INF/context.xml

許可しているIPアドレスのところは<!-- -->でコメントアウトできます。

```xml:context.xml 
          <!--
 <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

          -->
```   

#### 画面確認

実際に画面を確認します。
※Tomcatが起動していない場合は以下のコマンドで起動します。

    root@be401ef0872b:/usr/local/tomcat# /usr/local/tomcat/bin/startup.sh

 このhttp://localhost:8012/manager/html にアクセスして、先ほど設定したIDとパスワードでログインすると以下の画面が表示されます。
→ 今回はmisaka/passwordです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/58eb04a9-02cb-96cc-6049-2bc8876afa20.png)

## Jenkinsの設定

次にJenkinsの設定を行います。
Jenkinsでやることは、プラグインのインストールとジョブの作成になります。

#### Deploy to container プラグインのインストール

Jenkinsの初期設定を済ませたら、「Deploy to container」プラグインのインストールを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/b53ad6ff-c82d-84e3-8514-daf32231bf15.png)

#### パイプラインジョブの作成

ジョブを作成します。
パイプラインのジョブを作成したら、以下の画像のように設定します。
リポジトリURLには自身のGitHubのプロジェクトを指定してください。
また、GitHubでリポジトリを作った時の初回コミットのブランチをmainにすることが多いかもしれないので、Jenkinsのブランチ指定子には存在するブランチ名を入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/2c57445c-17a5-d353-b886-20d613cab718.png)


#### Pipeline Syntaxの設定

ジョブを選択した時の画面の左メニューにPipeline Syntaxをクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/362f978f-524b-d692-4316-8100e5c2a0d8.png)


Sample Stepに「deploy: Deploy war/ear to a container」を選択して
WAR/EAR filesは「**/*.war」と入力します。
認証情報の追加をしたらGenerate Pipeline Scriptを押してスクリプトの生成をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/c3a0cc08-d82f-759e-b77e-a04b269406b7.png)


※追加ボタンを押して以下のような認証情報を追加します(Tomcatで設定したユーザー名とパスワード)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/b1b1f459-6996-5713-2e4a-711a69248f2a.png)

Generate Pipeline Scriptを押下して出力されたスクリプトをJenkinsfileで利用します。


Javaのプロジェクトと一緒にJenkinsfileをGithubに上げていますが、以下のような内容になっています。
やっていることは単純です。先ほどGenerateしたスクリプトはデプロイステージで利用しています。

```groovy:jenkinsfile
pipeline { 
    agent any 
    options {
        skipStagesAfterUnstable()
    }
    stages {
        stage('Build') { 
            steps {
            	echo 'Build..' 
            	checkout([$class: 'GitSCM', branches: [[name: '*/main']],
     			userRemoteConfigs: [[url: 'https://github.com/jirentaicho/jenkinstest.git']]])
            	sh './mvnw clean compile'
            }
        }
        stage('Test'){
            steps {
                echo 'Test..'
                sh './mvnw test'
            }
        }
        stage('Make war file'){
        	steps {
        		echo 'Make war'
        		sh './mvnw package'
        	}
        }
        stage('Deploy') {
            steps {
                echo 'Deploy..'
                deploy adapters: [tomcat9(credentialsId: 'tomcat_misaka', path: '', url: 'http://192.168.11.13:8012')], contextPath: null, war: '**/*.war'
            }
        }
    }
}
```

#### ジョブ実行

ジョブ実行してコンソールを確認して「Finished: SUCCESS」となっていればデプロイまでOKです。

デプロイが完了したら、結果を見てみます。
今回はmyprojectというwarをデプロイしたので、myprojectというフォルダができています。
そしてJavaではapi/helloにアクセスしたときにメッセージを返すという素晴らしいプロジェクトを作っていたのでhttp://localhost:8012/myproject/api/hello にアクセスしてレスポンスが受け取れることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1835982/e6ee42f7-c389-cf56-45e9-d2889822695d.png)

## 終わりに


Jenkinsのプラグインを使うことで面倒な作業をスキップできたりするのも魅力だと感じました。
今回の場合はデプロイをプラグインに任せましたが、もしかしたらSSHで接続してってのが必要になったかと思います。
仕事ではGitHubにpushしたらビルドされてました。

基本的な所は学べたかと思います。