docker for macでjavaのwebアプリの開発環境を作る part2


# はじめに

[part1](http://qiita.com/cnaos/items/71593db7321b7eb071a7)ではdockerでtomcatを動かすところまでやりました。
今回はwebアプリケーション(war)のデプロイとデバッグまで進めたいと思います。


今回は以下の4つを行います。
warのビルドとデプロイにはmavenを使います。
デバッグにはIntelliJ IDEAを使います。

1. [デプロイ用にtomcatのwebアプリケーションマネージャを有効にする。](#デプロイ用にtomcatのwebアプリケーションマネージャを有効にする)
2. [デプロイ用のサンプルwarを作成する。](#デプロイ用のサンプルwarを作成する)
3. [warをデプロイする。](#warをデプロイする)
4. [デプロイしたwebアプリケーションにデバッガ接続して動作を止める。](#デプロイしたwebアプリケーションにデバッガ接続して動作を止める)


# デプロイ用にtomcatのwebアプリケーションマネージャを有効にする

warのデプロイ用にtomcatのwebアプリケーションマネージャを有効にする必要があり、
そのためにはtomcatの設定ファイル「tomcat-users.xml」を修正してユーザとパスワードを定義する必要があります。

dockerを使う場合、設定ファイルなどの修正に関してはイメージは変更せずに、変更した設定ファイルをコンテナにマウントして読み込むようにするのがよさそうだったので、そのようにしています。

## tomcatの設定ファイルを取り出す

### dockerで動いているtomcatのコンテナ名を調べる

```console:console
$ docker ps

CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                                                                           NAMES
1bf4ec739fab        tomcat:8.0-jre8                 "catalina.sh jpda run"   31 minutes ago      Up 16 minutes       0.0.0.0:8000->8000/tcp, 0.0.0.0:9090->9090/tcp, 8080/tcp                        qiitadockertomcat8_tomcat_1
96067c3ea144        codekitchen/dinghy-http-proxy   "/app/docker-entry..."   3 months ago        Up About an hour    0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 19322/tcp, 0.0.0.0:19322->19322/udp   http-proxy
```

この場合は ```qiitadockertomcat8_tomcat_1``` がtomcatが動いているコンテナの名前です。


### コンテナに入ってtomcatの設定ファイルのパスを調べる

コンテナ名がわかったので、次はどのパスからコピーしたらよいか調べるためにコンテナに入って中身を見てみます。


```console:console
$ docker exec -it qiitadockertomcat8_tomcat_1 bash

root@1bf4ec739fab:/usr/local/tomcat# ls -la
total 128
drwxr-sr-x 1 root staff  4096 Apr  3 20:02 .
drwxrwsr-x 1 root staff  4096 Apr  3 20:02 ..
-rw-r--r-- 1 root root  57011 Mar 28 14:45 LICENSE
-rw-r--r-- 1 root root   1444 Mar 28 14:45 NOTICE
-rw-r--r-- 1 root root   6741 Mar 28 14:45 RELEASE-NOTES
-rw-r--r-- 1 root root  16195 Mar 28 14:45 RUNNING.txt
drwxr-xr-x 2 root root   4096 Apr  3 20:03 bin
drwxr-xr-x 1 root root   4096 Aug  6 05:10 conf
drwxr-sr-x 3 root staff  4096 Apr  3 20:02 include
drwxr-xr-x 2 root root   4096 Apr  3 20:02 lib
drwxr-xr-x 1 root root   4096 Aug  6 05:10 logs
drwxr-sr-x 3 root staff  4096 Apr  3 20:02 native-jni-lib
drwxr-xr-x 2 root root   4096 Apr  3 20:02 temp
drwxr-xr-x 7 root root   4096 Mar 28 14:44 webapps
drwxr-xr-x 1 root root   4096 Aug  6 05:10 work

root@1bf4ec739fab:/usr/local/tomcat# ls -la conf
total 228
drwxr-xr-x 1 root root    4096 Aug  6 05:10 .
drwxr-sr-x 1 root staff   4096 Apr  3 20:02 ..
drwxr-xr-x 3 root root    4096 Aug  6 05:10 Catalina
-rw------- 1 root root   12767 Mar 28 14:45 catalina.policy
-rw------- 1 root root    7299 Mar 28 14:45 catalina.properties
-rw------- 1 root root    1577 Mar 28 14:45 context.xml
-rw------- 1 root root    3387 Mar 28 14:45 logging.properties
-rw------- 1 root root    6458 Mar 28 14:45 server.xml
-rw------- 1 root root    2164 Mar 28 14:45 tomcat-users.xml
-rw------- 1 root root    2634 Mar 28 14:45 tomcat-users.xsd
-rw------- 1 root root  168378 Mar 28 14:45 web.xml

root@1bf4ec739fab:/usr/local/tomcat# exit
```

docker内のtomcatの設定ファイルのフォルダは ```/usr/local/tomcat/conf``` のようです。
パスが分かったので、exitでコンテナから抜けます。

### dockerコンテナからtomcatの設定ファイルを取り出す

以下のコマンドでdockerコンテナのtomcatからconfフォルダを取り出します。
コマンド実行時のカレントディレクトリはdokcer-compose.ymlがおいてあるフォルダです。

```console:console
$ docker cp qiitadockertomcat8_tomcat_1:/usr/local/tomcat/conf conf
```

取り出したconfディレクトリを確認してみます。

```console:console
$ ls
conf               docker-compose.yml

$ ls -la conf
total 432
drwxr-xr-x  11 cnaos  staff     374  8  6 14:10 .
drwxr-xr-x   4 cnaos  staff     136  8  6 15:03 ..
drwxr-xr-x   3 cnaos  staff     102  8  6 14:10 Catalina
-rw-------   1 cnaos  staff   12767  3 28 23:45 catalina.policy
-rw-------   1 cnaos  staff    7299  3 28 23:45 catalina.properties
-rw-------   1 cnaos  staff    1577  3 28 23:45 context.xml
-rw-------   1 cnaos  staff    3387  3 28 23:45 logging.properties
-rw-------   1 cnaos  staff    6458  3 28 23:45 server.xml
-rw-------   1 cnaos  staff    2164  3 28 23:45 tomcat-users.xml
-rw-------   1 cnaos  staff    2634  3 28 23:45 tomcat-users.xsd
-rw-------   1 cnaos  staff  168378  3 28 23:45 web.xml
```

## とりだしたtomcat-users.xmlを修正してデプロイ用のアカウントを追加する

とりだしたtomcat-users.xmlを以下のように修正します。

ロールとして ```manager-gui``` と ```manager-script``` を持っているユーザを作成する必要があります。
パスワード部分は適当に自分で書き換えて設定してください。

```xml:tomcat-users.xml
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="tomcat" password="【適切なパスワードを設定してください】" roles="manager-gui,manager-script"/>

</tomcat-users>
```

## docker-compose.ymlを修正して、取り出したconfディレクトリをマウントする

docker-compose.ymlを以下のように修正します。
commandの前にvolumesを追加しています。

```yaml:docker-compose.yml
tomcat:
  image: tomcat:8.0-jre8
  ports:
    - "8000:8000"
    - "9090:9090"
  environment:
    VIRTUAL_HOST: tomcat.docker
    VIRTUAL_PORT: 8080
    CATALINA_OPTS: "-Dcom.sun.management.jmxremote
     -Dcom.sun.management.jmxremote.port=9090
     -Dcom.sun.management.jmxremote.rmi.port=9090
     -Dcom.sun.management.jmxremote.ssl=false
     -Dcom.sun.management.jmxremote.local.only=false
     -Dcom.sun.management.jmxremote.authenticate=false
     -Djava.rmi.server.hostname=tomcat.docker"
  volumes:
    - ./conf:/usr/local/tomcat/conf
  command: catalina.sh jpda run
```

修正したら、いちどdocker-composeの動いているコンソールでCTRL-Cを入力してコンテナを終了させ、
再び ```docker-compose up``` でコンテナを起動します。

## 作成したtomcaのユーザの確認をする

http://tomcat.docker/manager/html/list

にアクセスして先程設定したユーザとパスワードを入力します。

以下のような画面が表示されたらOKです。
![スクリーンショット 2017-08-06 15.33.35.png](https://qiita-image-store.s3.amazonaws.com/0/19321/4a360802-d0f7-66f9-1318-011c4ed42b76.png "スクリーンショット 2017-08-06 15.33.35.png")

以上でtomcatのwebアプリケーションマネージャを使ってwarをデプロイできるようになりました。

# デプロイ用のサンプルwarを作成する

今回はspring-bootのサンプルを使います。
warが作れるものであれば何でも構いません。

https://spring.io/guides/gs/spring-boot/

## プロジェクトのセットアップ

spring-bootのプロジェクトをdocker-compose.ymlがあるフォルダとは別のフォルダにgit cloneします。

```console:console
git clone https://github.com/spring-guides/gs-spring-boot.git
```

IDEでgs-spring-boot/completeの方のフォルダをプロジェクトとして開きます。


## spring-bootをwarを作るように変更

spring-bootのデフォルトの状態だとwarを作成しないので、warを作成するように変更します。

参考：http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-create-a-deployable-war-file


### Applicationクラスの修正

Application.javaを次のように変更します。
もとのApplication.javaを全体的に書き換えてください。

```java:Application.java
@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

}
```

### pom.xmlの修正

pom.xmlをのbuildタグの上のあたりに以下の設定を追加

```xml:pom.xml
<packaging>war</packaging>
```

pom.xmlのdependencyに以下を追加

```xml:pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

```


参考:
http://qiita.com/ARS_2000/items/3f191aeb6f161101d5f6


## warを作成する

gs-spring-boot/completeのディレクトリで、以下のコマンドを入力してwarを作成します。

```console:console
$ mvn war:war

Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building gs-spring-boot 0.1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-war-plugin:2.6:war (default-cli) @ gs-spring-boot ---
[INFO] Packaging webapp
[INFO] Assembling webapp [gs-spring-boot] in [/Users/cnaos/workbench/gs-spring-boot/complete/target/gs-spring-boot-0.1.0]
[INFO] Processing war project
[INFO] Webapp assembled in [269 msecs]
[INFO] Building war: /Users/cnaos/workbench/gs-spring-boot/complete/target/gs-spring-boot-0.1.0.war
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.288 s
[INFO] Finished at: 2017-08-06T16:25:04+09:00
[INFO] Final Memory: 19M/178M
[INFO] ------------------------------------------------------------------------
```


# warをデプロイする

## pom.xmlにtomcatへのデプロイ用mavenプラグインを追加する


```xml:pom.xml
    <build>
         <plugins>
            ...
         
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <server>tomcat-docker</server>
                    <url>http://tomcat.docker/manager/text</url>
                </configuration>
            </plugin>
           
            ...
         </plugins>
    </build>
```

configurationのserverタグの内側の値は、あとで出て来るsettings.xmlに書いてあるデプロイ用のユーザIDとパスワードを取り出すために使われます。

configurationのurlタグの内側の値は、tomcatのwebアプリケーションマネージャのURLです。
デフォルト値は ```http://localhost:8080/manager/text``` ですが、docker上のtomcatにデプロイするので変更します。


## mavenのtomcatプラグインがデプロイのために使う認証情報を設定する

ホームディレクトリ以下にmaven用の隠しディレクトリ「.m2」があります。この.m2ディレクトリにあるsettings.xmlに以下の設定を追加します。
settings.xmlファイルがなければsettings.xmlファイルを作成します。

パスワードはtomcat-users.xmlで設定したパスワードを設定してください。

```xml:~/.m2/settings.xml
<settings>
  <servers>
    <server>
      <id>tomcat-docker</id>
      <username>tomcat</username>
      <password>【tomcat-users.xmlで設定したパスワード】</password>
    </server>
  </servers>
</settings>
```

## デプロイする


```console:console
$ mvn tomcat7:deploy -Dmaven.test.skip=true
```

## デプロイしたwarをwebアプリケーションマネージャで確認する

http://tomcat.docker/manager/html/list

にアクセスするとデプロイされているwebアプリケーションの一覧が表示されるので、```gs-spring-boot``` がデプロイされていることを確認します。

![スクリーンショット_2017-08-06_17_18_03.png](https://qiita-image-store.s3.amazonaws.com/0/19321/6dc8c29f-da42-16db-1fec-5c79ef4e325b.png "スクリーンショット_2017-08-06_17_18_03.png")


## デプロイしたwarにアクセスしてみる

webアプリケーションマネージャの左端にあるパス列からそのまま
warにアクセスできるので、```/gs-spring-boot``` のリンクをクリックします。

```
Greetings from Spring Boot!
```

という文字列が表示されるはずです。

![スクリーンショット 2017-08-06 17.21.49.png](https://qiita-image-store.s3.amazonaws.com/0/19321/17690108-28f8-bac3-9e10-4ac6be33d56c.png "スクリーンショット 2017-08-06 17.21.49.png")


# デプロイしたwebアプリケーションにデバッガ接続して動作を止める

## docker-composeのtomcatの起動設定にデバッガ用のポートと接続アドレスを設定する

```VIRTUAL_PORT: 8080```
の次の行に
```JPDA_ADDRESS: 8000```
を追加します。


```xml:docker-compose.yml
tomcat:
  image: tomcat:8.0-jre8
  ports:
    - "8000:8000"
    - "9090:9090"
  environment:
    VIRTUAL_HOST: tomcat.docker
    VIRTUAL_PORT: 8080
    JPDA_ADDRESS: 8000
    CATALINA_OPTS: "-Dcom.sun.management.jmxremote
     -Dcom.sun.management.jmxremote.port=9090
     -Dcom.sun.management.jmxremote.rmi.port=9090
     -Dcom.sun.management.jmxremote.ssl=false
     -Dcom.sun.management.jmxremote.local.only=false
     -Dcom.sun.management.jmxremote.authenticate=false
     -Djava.rmi.server.hostname=tomcat.docker"
  volumes:
    - ./conf:/usr/local/tomcat/conf
  command: catalina.sh jpda run
```

追加したら、docker-composeを再起動します。



## IDEで、デバッガのリモート接続設定を作成する。

1. IntelliJのメニューのRun>Edit Configurations..を選ぶ
2. Run/Debug Configurationsパネルが開くので、+ボタンを押す
3. Add New Configurationの中から「Remote」を選ぶ
4. SettingsのHostに「tomcat.docker」を設定する
5. SettingsのPortに「8000」を設定する

以上を設定すると、こんな感じになります。

![スクリーンショット 2017-08-06 18.41.35.png](https://qiita-image-store.s3.amazonaws.com/0/19321/996a66cd-080e-9c2a-f844-ad39d2804d5c.png "スクリーンショット 2017-08-06 18.41.35.png")


## デバッガのリモート接続を実行する

作成したデバッガのリモート接続を実行します。

デバッガのコンソールに以下のように表示されていれば、デバッガの接続が成功しています。

```
Connected to the target VM, address: 'tomcat.docker:8000', transport: 'socket'
```

## ブレークポインタを設定して確認する

HelloController.javaのindexメソッドにブレークポインタを設置します。
ブラウザから
http://tomcat.docker/gs-spring-boot/
にアクセスしてみて、ブレークポインタで止まれば成功です。