如何在Docker机器中将JMX从主机连接到Docker容器?

问题描述 投票:5回答:2

当我直接在主机上运行Docker容器时,可以毫无问题地连接到它。

我的主机有网络192.168.1.0/24,主机的IP地址是192.168.1.20。我的Docker容器的IP地址为172.17.0.2。当我从jconsole连接到172.17.0.2:1099时,它可以工作。

当我将此服务放入Docker机器时,无法连接到它。

我的Docker机器有IP 192.168.99.100,其中的容器有IP地址172.17.0.2但是当我使用jconsole连接到192.168.99.100:1099时它不起作用。

重复一遍:

192.168.1.20 --- 172.17.0.2:1099有效

192.168.1.20 ---(192.168.99.100 --- 172.17.0.2:1099)并从我的主机连接到192.168.99.100:1099不起作用。

值得一提的是,我可以通过Docker机器的外部IP地址访问Docker机器中的容器化服务,例如:这将工作:

192.168.99.100 --- (192.168.99.100:8080 --- 172.17.0.2:8080)

但是当我使用JMX时,它就无法正常工作。

这是Tomcat服务。我在启动Tomcat实例的脚本中有这个:

CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n \
-Dcom.sun.management.jmxremote.port=1099 \
-Dcom.sun.management.jmxremote.rmi.port=1099 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=IP address of Docker container 
tomcat networking docker jmx docker-machine
2个回答
6
投票

我认为问题可能是java.rmi.server.hostname财产的价值。这需要是JMX客户端用于连接到JVM的主机名或IP地址。这是第一种使用172.17.0.2:1099直接连接到容器的情况,此设置需要设置为172.17.0.2。在后一种情况下,您通过192.168.99.100:1099上的docker机器访问容器,需要将设置设置为192.168.99.100

在我研究一个非常相似的问题(在此期间被删除)期间,我偶然发现了一篇博客文章(同时也被删除了)。虽然它相当陈旧但它让我了解JMX连接如何工作:

  1. JMX注册表侦听容器的端口<com.sun.management.jmxremote.port>
  2. 如果使用JConsole连接到注册表,则注册表会向客户端提供JMX服务URL。
  3. 客户端使用此URL来获取JMX对象

服务URL看起来像这个service:jmx:rmi:///jndi/rmi://<java.rmi.server.hostname>:<com.sun.management.jmxremote.rmi.port>/jmxrmi。在你的情况下service:jmx:rmi:///jndi/rmi://172.17.0.2:1099/jmxrmi。由于此地址只能从泊坞机内部访问,因此无法从远程连接。在我的问题中,我讨论了与RMI端口相同的问题......

似乎没有一个解决这个问题的开箱即用的解决方案。但是,如同建议的here,可以在容器启动时提供JMX端口和外部主机名(或IP)作为环境变量。然后可以在JMX配置中使用它们:

docker run -p 1099:1099 \
    -e "JMX_HOST=192.168.99.100" \
    -e "JMX_PORT=1099" \
    company/tomcat:8.0.30

CATALINA_OPTS="... \
    -Dcom.sun.management.jmxremote=true \
    -Dcom.sun.management.jmxremote.port=$JMX_PORT \
    -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    -Djava.rmi.server.hostname=$JMX_HOST"

不是很好,但它应该工作......


1
投票

如果有人有问题。我已经使用以下参数在docker容器中启动了java进程:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9876 
-Dcom.sun.management.jmxremote.rmi.port=9876 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Djava.rmi.server.hostname=<name of the docker container>

重要的是设置docker容器的名称。 EXPOSE容器9876中的端口。我还设置了一个ssh连接并将9876转发到localhost。

以下内容适用于您的SSH配置:

LocalForward 127.0.0.1:9876 127.0.0.1:9876

我也在本地机器上设置了/ etc / hosts

127.0.0.1 <name of the docker container>

现在将控制台连接到“docker容器的名称”

© www.soinside.com 2019 - 2024. All rights reserved.