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


# はじめに
とりあえず開発環境まで作成できればいいというところを目標にしており、dockerを使って本番運用をするところまでは対象としていません。

具体的には、ローカルの開発環境のdocker上でtomcat8を動かし、
IDEなどからwebapp用のwarをデプロイして動作確認できることを目標とします。

また、これらの操作に必要になるdocker for macやdockerコマンド、docker-composeコマンドなどのインストール手順の説明は省きます。

今回は以下の2つを行います。

1. dinghy-http-proxy環境を作る
2. docker環境でtomcatを動かす

webアプリのデプロイについては次回説明します。


# 必要になるパッケージとかコマンドとか
- docker for mac(アプリケーション)
- docker-compose(コマンド)
	- dockerコンテナに色々なパラメタを渡すのに便利なので使います。
	- brewでインストールします
- dinghy-http-proxy
	- ローカル環境からdockerコンテナにアクセスする際に便利なので。

## 動作確認したバージョン情報

```コマンド
docker version
Client:
 Version:      17.03.1-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Tue Mar 28 00:40:02 2017
 OS/Arch:      darwin/amd64

Server:
 Version:      17.03.1-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   c6d412e
 Built:        Fri Mar 24 00:00:50 2017
 OS/Arch:      linux/amd64
 Experimental: true
```

```コマンド
docker-compose --version
docker-compose version 1.11.2, build dfed245
```



# dinghy-http-proxy環境を作る

https://github.com/codekitchen/dinghy-http-proxy

これはdocker環境用のリバースproxy兼DNSサーバです。
これを入れて設定しておくと、http://tomcat.docker/ というURLでdocker環境内のtomcatコンテナにアクセスできるようになります。
分かりやすいですね。

## dinghy-http-proxyを起動する

```コマンド
docker run -d --restart=always \
  -v /var/run/docker.sock:/tmp/docker.sock:ro \
  -v ~/.dinghy/certs:/etc/nginx/certs \
  -p 80:80 -p 443:443 -p 19322:19322/udp \
  -e DNS_IP=127.0.0.1 -e CONTAINER_NAME=http-proxy \
  --name http-proxy \
  codekitchen/dinghy-http-proxy
```

## docker ps でdinghy-http-proxyのプロセスが動いている事を確認する

```コマンド
docker ps
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS              PORTS                                                                           NAMES
96067c3ea144        codekitchen/dinghy-http-proxy   "/app/docker-entry..."   47 seconds ago      Up 45 seconds       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
```

## macのDNSリゾルバに設定を追加する。

`/etc/resolver/`に「docker」という名前のファイルを作成し、
以下のような内容を記述してください。
これでdockerドメインの問い合わせがあると、dinghy-http-proxyのDNSサーバへ問い合わせが行くようになります。

```/etc/resolver/docker
nameserver 127.0.0.1
port 19322
```

## dockerでphpを動かしてdinghy-http-proxyの動作を確認する。

```コマンド
docker run -it --name testphp --expose 80 --env VIRTUAL_HOST=testphp.docker php php -S 0.0.0.0:80
```

ブラウザでtestphp.dockerにアクセスしてみて、
コンソールにログが出ればOKです。

```コンソールログ
PHP 7.1.3 Development Server started at Sat Apr 15 02:53:30 2017
Listening on http://0.0.0.0:80
Document root is /
Press Ctrl-C to quit.
[Sat Apr 15 02:53:44 2017] 172.17.0.2:40528 [404]: / - No such file or directory
[Sat Apr 15 02:53:45 2017] 172.17.0.2:40530 [404]: /favicon.ico - No such file or directory
```


確認が終わったら、phpを起動したコンソールにCTRL-Cを送って終了させます。

確認のために使ったコンテナも不要なので削除します。

```コマンド
docker rm testphp 
```

# docker環境でtomcatを動かす

## docker-composeファイルの作成

空のディレクトリを作ってその中に以下のようなdocker-compose.ymlファイルを作成してください。


```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"
  command: catalina.sh jpda run
```

9090がJMX接続用ポート、
8000がデバッガ(JPDA)接続用ポートです。
8080ポートはdinghy-http-proxy経由で接続するためportsでの公開指定は不要です。

環境変数のVIRTUAL_HOSTとVIRTUAL_PORTはdinghy-http-proxy用の設定で、
これでmacから http://tomcat.docker/ をブラウザで開くと
dockerコンテナの8080ポートに接続されます。


## docker-composeでtomcatを起動する

docker-compose.ymlと同じディレクトリに移動して、以下のコマンドを実行するとtomcat8のコンテナが起動します。

```コマンド
docker-compose up
```

```docker-composeのログ
Starting tomcat8docker_tomcat_1
Attaching to tomcat8docker_tomcat_1
tomcat_1  | Listening for transport dt_socket at address: 8000
tomcat_1  | 15-Apr-2017 03:39:25.168 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/8.0.43
tomcat_1  | 15-Apr-2017 03:39:25.173 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Mar 28 2017 14:42:59 UTC
tomcat_1  | 15-Apr-2017 03:39:25.174 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number:         8.0.43.0
tomcat_1  | 15-Apr-2017 03:39:25.175 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
tomcat_1  | 15-Apr-2017 03:39:25.175 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            4.9.13-moby
tomcat_1  | 15-Apr-2017 03:39:25.177 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
tomcat_1  | 15-Apr-2017 03:39:25.177 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/lib/jvm/java-8-openjdk-amd64/jre
tomcat_1  | 15-Apr-2017 03:39:25.178 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_121-8u121-b13-1~bpo8+1-b13
tomcat_1  | 15-Apr-2017 03:39:25.182 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
tomcat_1  | 15-Apr-2017 03:39:25.182 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /usr/local/tomcat
tomcat_1  | 15-Apr-2017 03:39:25.183 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /usr/local/tomcat
tomcat_1  | 15-Apr-2017 03:39:25.190 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
tomcat_1  | 15-Apr-2017 03:39:25.192 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
tomcat_1  | 15-Apr-2017 03:39:25.193 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
tomcat_1  | 15-Apr-2017 03:39:25.194 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
tomcat_1  | 15-Apr-2017 03:39:25.196 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -agentlib:jdwp=transport=dt_socket,address=localhost:8000,server=y,suspend=n
tomcat_1  | 15-Apr-2017 03:39:25.197 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote
tomcat_1  | 15-Apr-2017 03:39:25.198 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote.port=9090
tomcat_1  | 15-Apr-2017 03:39:25.200 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote.rmi.port=9090
tomcat_1  | 15-Apr-2017 03:39:25.201 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote.ssl=false
tomcat_1  | 15-Apr-2017 03:39:25.202 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote.local.only=false
tomcat_1  | 15-Apr-2017 03:39:25.202 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcom.sun.management.jmxremote.authenticate=false
tomcat_1  | 15-Apr-2017 03:39:25.204 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.rmi.server.hostname=tomcat.docker
tomcat_1  | 15-Apr-2017 03:39:25.205 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.endorsed.dirs=/usr/local/tomcat/endorsed
tomcat_1  | 15-Apr-2017 03:39:25.206 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
tomcat_1  | 15-Apr-2017 03:39:25.206 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
tomcat_1  | 15-Apr-2017 03:39:25.208 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
tomcat_1  | 15-Apr-2017 03:39:25.211 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded APR based Apache Tomcat Native library 1.2.12 using APR version 1.5.1.
tomcat_1  | 15-Apr-2017 03:39:25.212 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
tomcat_1  | 15-Apr-2017 03:39:25.224 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized (OpenSSL 1.1.0e  16 Feb 2017)
tomcat_1  | 15-Apr-2017 03:39:25.402 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-apr-8080"]
tomcat_1  | 15-Apr-2017 03:39:25.428 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-apr-8009"]
tomcat_1  | 15-Apr-2017 03:39:25.434 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 785 ms
tomcat_1  | 15-Apr-2017 03:39:25.494 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service Catalina
tomcat_1  | 15-Apr-2017 03:39:25.504 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.0.43
tomcat_1  | 15-Apr-2017 03:39:25.527 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/host-manager
tomcat_1  | 15-Apr-2017 03:39:26.172 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/host-manager has finished in 645 ms
tomcat_1  | 15-Apr-2017 03:39:26.175 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/ROOT
tomcat_1  | 15-Apr-2017 03:39:26.227 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/ROOT has finished in 52 ms
tomcat_1  | 15-Apr-2017 03:39:26.230 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/manager
tomcat_1  | 15-Apr-2017 03:39:26.293 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/manager has finished in 63 ms
tomcat_1  | 15-Apr-2017 03:39:26.294 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/docs
tomcat_1  | 15-Apr-2017 03:39:26.353 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/docs has finished in 60 ms
tomcat_1  | 15-Apr-2017 03:39:26.355 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /usr/local/tomcat/webapps/examples
tomcat_1  | 15-Apr-2017 03:39:26.700 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /usr/local/tomcat/webapps/examples has finished in 345 ms
tomcat_1  | 15-Apr-2017 03:39:26.707 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-8080"]
tomcat_1  | 15-Apr-2017 03:39:26.728 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-apr-8009"]
tomcat_1  | 15-Apr-2017 03:39:26.752 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 1317 ms
```

## tomcatのページを表示してみる


ブラウザで以下のURLを表示してみます。

http://tomcat.docker/

tomcatのwelcomeページが表示されたでしょうか？

![スクリーンショット 2017-04-15 12.42.11.png](https://qiita-image-store.s3.amazonaws.com/0/19321/d2a6c1b3-0059-aabc-c1ce-6c675c511c0a.png "tomcat.png")



## JMX接続してみる

```コマンド
jconsole tomcat.docker:9090
```

jconsoleでメモリの利用状況などが確認できたでしょうか？


![jconsole2.png](https://qiita-image-store.s3.amazonaws.com/0/19321/4864c75a-2b3f-d005-36b5-0df073d7c810.png "jconsole2.png")

![jconsole1.png](https://qiita-image-store.s3.amazonaws.com/0/19321/56e7a4fb-f5cb-69b1-2724-5d848f950fed.png "jconsole1.png")

## dockerコンテナで動いているtomcatへのJMX接続に関して

重要なのは以下の2つのシステムプロパティです。

* com.sun.management.jmxremote.rmi.port
* java.rmi.server.hostname

以下の記事を参考にしました。
http://d.hatena.ne.jp/Kazuhira/20141112/1415782056


### com.sun.management.jmxremote.rmi.port

JMXのリモート接続では2つのポート番号を使い、そのうちの片方のポート番号が不定だったため、ファイヤウォールなどがあるとjava7update4以前は接続できませんでした。

dockerも基本的に明示的にポートを指定して公開しないと接続できないので、
このプロパティを指定してJMX接続に使うポートを固定したうえで、
そのポートをマッピングしてmac側に公開する必要があります。

以下の記事を参考にしました。
http://tech.furyu.jp/blog/?p=3467


### java.rmi.server.hostname

https://ptmccarthy.github.io/2014/07/24/remote-jmx-with-docker/

とか

https://forums.docker.com/t/enable-jmx-rmi-access-to-a-docker-container/625

によれば、JavaVM起動時のシステムプロパティ`java.rmi.server.hostname`
にdockerのIPアドレスを設定しておけばいいらしいです。

今回の場合は、ローカルマシンでdockerを動かしているので`127.0.0.1`を指定しておけばOKですが、
`tomcat.docker`を指定してもDNS問い合わせで127.0.0.1に変換されるんでどっちでもいいみたいです。