实际上我想要一个适用于JEE容器的解决方案,特别是Glassfish,但在我尝试了很多设置组合并且没有成功之后,我将设置简化为最简单的情况。
这是我在Docker容器中启动的Hello World守护进程。我想将jconsole
或VisulaVM
附加到其中。一切都在同一台机器上。
public class Main {
public static void main(String[] args) {
while (true) {
try {
Thread.sleep(3000);
System.out.println("Hello, World");
} catch (InterruptedException e) {
break;
}
}
}
}
Dockerfile
FROM java:8
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", "Main"]
建立:docker build -t hello-world-daemon .
正在运行:docker run -it --rm --name hwd hello-world-daemon
问题:
CMD
命令行?我没有在这里展示我失败的尝试,因此正确答案不会有偏见。这应该是一个非常常见的问题,但我找不到可行的解决方案。
更新。工作解决方案
此Dockerfile正常工作
FROM java:8
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", \
"-Dcom.sun.management.jmxremote", \
"-Dcom.sun.management.jmxremote.port=9010", \
"-Dcom.sun.management.jmxremote.local.only=false", \
"-Dcom.sun.management.jmxremote.authenticate=false", \
"-Dcom.sun.management.jmxremote.ssl=false", "Main"]
EXPOSE 9010
与docker run命令结合使用
docker run -it --rm --name hwd -p 9010:9010 hello-world-daemon
VisualVM
通过右键单击 Local->添加JMX连接,然后输入localhost:9010
或通过添加远程主机来连接。
JConsole
通过选择远程进程与localhost:9010
进行连接。
将连接定义为远程时,可以使用ifconfig
列出的任何接口。例如,地址docker0
的{{1}}接口有效。容器的地址172.17.0.1
也有效。
答案 0 :(得分:37)
首先,您应该使用这些JVM参数运行应用程序:
class Foo: x=MyDescritptor(); y=x
然后你应该为docker公开端口:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
还使用docker run命令指定端口绑定:
EXPOSE 9010
之后,您可以将Jconsole连接到本地9010端口并管理在Docker中运行的应用程序。
答案 1 :(得分:8)
我跟着an other SO response to a similar question并且有效。
我通过添加那些JVM参数来启动容器内的Java进程:
-Dcom.sun.management.jmxremote.port=<port> \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.rmi.port=<port> \
-Djava.rmi.server.hostname=$HOST_HOSTNAME
并启动Docker容器,为-e HOST_HOSTNAME=$HOSTNAME -p <port>
命令指定docker run
。
然后我通过添加远程JMX连接(&#34;文件&#34;&gt;&#34;添加JMX连接......)从本地JVisualVm访问此远程Java应用程序... &#34;)并在&#34;连接&#34;中指定<dockerhostname>:<port>
输入和检查&#34;不要求SSL连接&#34;。
答案 2 :(得分:2)
由Anthony回答。
我不得不在我的Windows机器上使用-Djava.rmi.server.hostname
java选项。
请确保不要在Dockerfile中使用JSON格式的CMD,因为这不支持shell扩展。
Dockerfile示例:
FROM java:8
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
#Do not use CMD in JSON format here because shell expansion doesn't work in JSON format
#Shell expansion is needed for the ${HOST} variable.
CMD java -Dcom.sun.management.jmxremote=true \
-Dcom.sun.management.jmxremote.rmi.port=9010 \
-Dcom.sun.management.jmxremote.port=9010 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.local.only=false \
-Djava.rmi.server.hostname=${HOST} \
Main
答案 3 :(得分:0)
对于仍然遭受类似以下错误的所有人:
就我而言,是我在Docker YML中为端口使用了不同的端口映射:
例如:
15100:9090
但是显然在端口绑定中,您必须为外部端口和内部端口分配 SAME端口!
参考: https://forums.docker.com/t/exposing-mapped-jmx-ports-from-multiple-containers/5287/5
答案 4 :(得分:0)
FWIW,这就是我将VisualVM附加到在macOS上运行的Docker容器内的Java进程的方式:
Main.java:
public class Main {
public static void main(String args[]) throws Exception {
while (true) {
System.out.print("Hello ");
System.out.println("world");
Thread.sleep(1000);
}
}
}
Dockerfile:
FROM openjdk:11.0.2-slim
COPY Main.class /
WORKDIR /
ENTRYPOINT ["java", \
"-Dcom.sun.management.jmxremote=true", \
"-Dcom.sun.management.jmxremote.port=9010", \
"-Dcom.sun.management.jmxremote.local.only=false", \
"-Dcom.sun.management.jmxremote.authenticate=false", \
"-Dcom.sun.management.jmxremote.ssl=false", \
"-Dcom.sun.management.jmxremote.rmi.port=9010", \
"-Djava.rmi.server.hostname=localhost", \
"Main"]
编译Java代码,构建映像并运行容器,如下所示:
$ javac Main.java
$ docker build -t main .
$ docker run -p 9010:9010 -it main
然后使用JMX将VisualVM附加到localhost:9010
答案 5 :(得分:0)
感谢大家将我引向正确的方向。最终,我在更复杂的配置中工作:通过本地计算机上Windows 10下的Docker Desktop通过Kubernetes。
我的应用程序的配置:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=30491
-Dcom.sun.management.jmxremote.rmi.port=30491
-Djava.rmi.server.hostname=localhost
Pod的端口:
ports:
- name: jmx
containerPort: 30491
protocol: TCP
服务的端口:
ports:
- name: jmx
nodePort: 30491
port: 9010
protocol: TCP
targetPort: jmx