使用映射端口访问Docker容器内的JMX

时间:2016-02-09 22:57:03

标签: docker port jmx

我正在尝试使用JMX访问在docker容器内运行的应用程序。

这与this question类似,当docker镜像内的端口映射到图像外部的相同端口时,该解决方案可以正常工作。但是,我有时想将端口映射到不同的端口。

我在托管应用程序中设置这些属性。

-Dcom.sun.management.jmxremote.port=9832 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.local.only=false 
-Dcom.sun.management.jmxremote.rmi.port=9832 
-Djava.rmi.server.hostname=192.168.99.100 
-Djava.rmi.server.logCalls=true

当docker容器将端口9832映射到9832时,这可以正常工作。我可以通过JConsole或我们自己的应用程序连接。如果端口被映射到另一个端口,那么我无法从JConsole或我们的应用程序访问该应用程序。

我怀疑一个或两个端口号需要是外部端口(就像java.rmi.server.hostname一样是外部地址,而不是内部地址)。但是,它失败了所有四种端口号组合。

其中两个组合不会从服务器生成日志输出。一个(我忘了哪个)产生这个输出:

Feb 09, 2016 10:35:54 PM org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl start
INFO: AMQ221001: Apache ActiveMQ Artemis Message Broker version 1.1.0 [nodeID=7a6e038e-cf7d-11e5-b566-31dc437b2d1a] 
HTTP Server started at http://0.0.0.0:8161
Feb 09, 2016 10:36:06 PM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-192.168.99.1: [192.168.99.1: sun.rmi.transport.DGCImpl[0:0:0, 2]: java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[], long, java.rmi.dgc.Lease)]
Feb 09, 2016 10:36:08 PM sun.rmi.transport.Transport serviceCall
FINE: RMI TCP Connection(1)-192.168.99.1: [192.168.99.1] exception: 
java.rmi.NoSuchObjectException: no such object in table
    at sun.rmi.transport.Transport.serviceCall(Transport.java:177)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Feb 09, 2016 10:40:24 PM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(2)-192.168.99.1: [192.168.99.1: sun.rmi.transport.DGCImpl[0:0:0, 2]: void clean(java.rmi.server.ObjID[], long, java.rmi.dgc.VMID, boolean)]

另一个产生此输出。

HTTP Server started at http://0.0.0.0:8161
Feb 09, 2016 10:14:13 PM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-192.168.99.1: [192.168.99.1: sun.management.jmxremote.SingleEntryRegistry[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)]
Feb 09, 2016 10:14:17 PM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-192.168.99.1: [192.168.99.1: sun.management.jmxremote.SingleEntryRegistry[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)]
Feb 09, 2016 10:14:17 PM sun.rmi.server.UnicastServerRef logCall
FINER: RMI TCP Connection(1)-192.168.99.1: [192.168.99.1: sun.management.jmxremote.SingleEntryRegistry[0:0:0, 0]: java.rmi.Remote lookup(java.lang.String)]

鉴于这些失败,我怀疑一个或两个端口属性的使用方式有时需要是内部端口,有时需要是外部端口。这意味着当端口映射到不同的位置时,无法进行JMX访问。

我可以通过telnet 192.168.99.100 <mapped port>访问映射端口,所以我知道映射正在运行。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,并且连续三天都放弃了,我做的解决方案虽然不好,但是可以用。因此,我的解决方案是:我没有在JMX连接上设置固定端口并使用其他外部端口将其映射,而是在docker-compose.yml上创建了一个名为JMX_MNG_PORT的环境变量。

...
ports:
  - '9011:9011'
...
environment:
  - JMX_MNG_PORT=9011
...

然后我在docker-entrypoint.sh上配置了JAVA_OPTS变量以接收JMX_MNG_PORT。

...
JAVA_OPTS=$JAVA_OPTS -Dcom.sun.management.jmxremote.port=${JMX_MNG_PORT}
JAVA_OPTS=$JAVA_OPTS -Dcom.sun.management.jmxremote.rmi.port=${JMX_MNG_PORT}
...

现在,在每个要配置的容器(docker-compose.yml)上,我只需要配置JMX_MNG_PORT并使用THE SAME NUMBER公开端口。

记住,我不知道为什么,但是如果您使用另一个端口,那么在jmxremote.port和jmxremote.rmi.port上配置的端口将无法工作。

我希望它能解决像我这样的人的情况。