如何使用 JMX 从主机连接到 Docker 机器中的 Docker 容器?
How to connect with JMX from host to Docker container in 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
我想问题大概出在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 连接是如何工作的:
- JMX 注册表侦听容器
<com.sun.management.jmxremote.port>
的端口
- 如果您使用 JConsole 连接到注册表,注册表会向客户端提供 JMX 服务 URL。
- 这个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
。由于此地址只能从 docker 机器内部访问,因此无法从远程连接。在我的问题中,我提到了关于 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"
不是很好,但应该可以...
如果有人遇到问题。我已经使用以下参数在 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 转发到本地主机。
以下是您的 SSH 配置:
LocalForward 127.0.0.1:9876 127.0.0.1:9876
我也在本地机器上设置了 /etc/hosts
127.0.0.1 <name of the docker container>
现在将您的控制台连接到 "name of the docker container"
当我的主机上直接有 运行 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
我想问题大概出在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 连接是如何工作的:
- JMX 注册表侦听容器
<com.sun.management.jmxremote.port>
的端口 - 如果您使用 JConsole 连接到注册表,注册表会向客户端提供 JMX 服务 URL。
- 这个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
。由于此地址只能从 docker 机器内部访问,因此无法从远程连接。在我的问题中,我提到了关于 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"
不是很好,但应该可以...
如果有人遇到问题。我已经使用以下参数在 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 转发到本地主机。
以下是您的 SSH 配置:
LocalForward 127.0.0.1:9876 127.0.0.1:9876
我也在本地机器上设置了 /etc/hosts
127.0.0.1 <name of the docker container>
现在将您的控制台连接到 "name of the docker container"