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

时间:2016-02-17 19:55:21

标签: tomcat networking docker jmx docker-machine

当我在主机上直接运行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 

2 个答案:

答案 0 :(得分:6)

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

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

  1. JMX注册表侦听容器的端口<com.sun.management.jmxremote.port>
  2. 如果使用JConsole连接到注册表,则注册表会向客户端提供JMX服务URL。
  3. 客户端使用此URL来获取JMX对象
  4. 服务网址如下所示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端口相同的问题......

    似乎并不是解决此问题的开箱即用解决方案。但是,可以在启动容器时将JMX端口和外部主机名(或IP)作为环境变量提供,如建议的here。然后可以在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 :(得分: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 container的名称”