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

9
我正在尝试通过JMX访问在Docker容器内运行的应用程序。
这类似于这个问题,当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 <映射端口>访问映射的端口,所以我知道映射正在工作。

你有检查过在没有日志记录的时间内,防火墙是否阻止了 Docker 容器所暴露的端口吗? - Tyagi Akhilesh
@TyagiAkhilesh 我可以使用 Telnet 连接到该端口,因此该端口是可访问的。 - Troy Daniels
从内存中,JMX 在初始连接时告诉客户端要连接的第二个端口。因此,客户端期望能够连接到应用程序配置的端口。只需使用映射的端口。如果您真的想使用不同的 NAT 端口,请使用 socks 代理。 - Matt
我们需要更多的赞来支持这个问题。 - bioffe
你尝试过使用两个不同的端口和不同的映射吗? - pandaadb
1个回答

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并使用相同的端口号来暴露端口。
请记住,我不知道为什么,但如果您使用的是jmxremote.port和jmxremote.rmi.port上配置的另一个端口,则它将无法工作。
我希望这能解决像我这样的其他人的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接