Dockerコンテナ内のJAVAプロセスに対してJMX接続する

外部からDockerコンテナ内のJAVAプロセスにJMX接続する場合、すんなり接続できませんでした。

大体のサイトでは、以下のようにすれば接続できると記載されてますが、このままコピペしてもJMX接続できません。

-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote=TRUE
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.port=9990
-Dcom.sun.management.jmxremote.rmi.port=9990
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

なぜかというとDockerコンテナ上でJAVAプロセス起動しているということは

windows(JConsoleなどのJMXクライアント) => Dockerサーバ(IPアドレスXXX) => Dockerコンテナ(IPアドレスYYY)

のようにIPアドレスXXXを経由してDockerコンテナ(IPアドレスYYY)に接続しようとしていることです。
Dockerコンテナに対してJMX接続しているからNGで、特殊な方法が必要なのでは?ということはなく、以下のような構成になっているということです。

windows(JConsoleなどのJMXクライアント) => 踏み台サーバ => JAVAアプリが動いているサーバ

なので、直接JConsole=>Dockerコンテナ(IPアドレスYYY)には接続することができません。
Dockerコンテナへ「0.0.0.0:9990->9990/tcp」を設定しているだけではダメでした。

重要なところは、java.rmi.server.hostname、com.sun.management.jmxremote.port、com.sun.management.jmxremote.rmi.portで

java.rmi.server.hostnameは、JMXクライアントがJMXサーバのポート(com.sun.management.jmxremote.port)に接続した際に、

JMXサーバ=>JMXクライアントへここへ接続してくれ、というIPアドレスを教えるようです。

なのでここで設定するものは、Dockerサーバ(IPアドレスXXX)で、以下のようにする必要があります。

-Djava.rmi.server.hostname=Dockerサーバ(IPアドレスXXX)

次のJMXクライアントの動きとしては、com.sun.management.jmxremote.rmi.portのポートに接続しにいきますが

これが設定されていないとJMXサーバがランダムで決めるようです。

ということはDockerコンテナへ「0.0.0.0:9990->9990/tcp」を設定していても、com.sun.management.jmxremote.rmi.portのポートがランダムで決まってしまうため、9990以外のポートはJMXクライアントが接続できないため接続エラーとなってしまいます。

com.sun.management.jmxremote.rmi.portはcom.sun.management.jmxremote.portと同じポートでも問題ないため、9990にしてしまえば「0.0.0.0:9990->9990/tcp」が有効なため接続できるようになります。

最終的には以下のように設定する必要があります。

-Djava.rmi.server.hostname=Dockerサーバ(IPアドレスXXX)
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote=TRUE
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.port=9990    ※Dockerコンテナへ外部接続を許可したポート
-Dcom.sun.management.jmxremote.rmi.port=9990  ※Dockerコンテナへ外部接続を許可したポート
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false