How do I attach VisualVM to a simple Java process running in a Docker container

后端 未结 6 1760
礼貌的吻别
礼貌的吻别 2020-12-12 14:35

Actually I wanted a solution working for JEE containers, specifically for Glassfish, but after I tried many combinations of settings and did not succeed, I reduced the setup

相关标签:
6条回答
  • 2020-12-12 14:50

    At first you should run you application with these JVM params:

    -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
    

    Then you should expose port for docker:

    EXPOSE 9010
    

    Also specify port binding with docker run command:

    docker run -p 9010:9010 -it --rm --name hwd hello-world-daemon
    

    After that you can connect with Jconsole to local 9010 port and manage application run in Docker.

    0 讨论(0)
  • 2020-12-12 14:52

    I followed an other SO response to a similar question and it worked.

    I started my Java process inside the container by adding those JVM params:

    -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
    

    and started the Docker container specifying -e HOST_HOSTNAME=$HOSTNAME -p <port> to the docker run command.

    Then I've been able to access to this remote Java app from my local JVisualVm by adding a remote JMX connection ("File" > "Add a JMX Connection...") and specifying <dockerhostname>:<port> in the "Connection" input, and checking "Do not require SSL connection".

    0 讨论(0)
  • 2020-12-12 14:53

    Thanks to all of you for routing me to the right direction. Finally I got it working in more complex config: Kubernetes via Docker Desktop under Windows 10 on local machine.

    My app's config:

    -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's port:

    ports:
    - name: jmx
      containerPort: 30491
      protocol: TCP
    

    Service's port:

    ports:
    - name: jmx
      nodePort: 30491
      port: 9010
      protocol: TCP
      targetPort: jmx
    
    0 讨论(0)
  • 2020-12-12 14:55

    To all of you that still suffer from an error like the below:

    In my case it was that i used in my Docker YML different port mappings for the ports:

    e.g:

    15100:9090
    

    but apparently in your port bindings you must assign the SAME port for external port and internal port !

    Reference: https://forums.docker.com/t/exposing-mapped-jmx-ports-from-multiple-containers/5287/5

    0 讨论(0)
  • 2020-12-12 14:59

    As answered by Anthony. I had to use the -Djava.rmi.server.hostname java option on my Windows machine.

    Just be sure not to use the CMD in JSON format in your Dockerfile as this doesn't support shell expansion.

    Dockerfile example:

    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
    
    0 讨论(0)
  • 2020-12-12 14:59

    FWIW, this is how I was able to attach VisualVM to a Java process inside a Docker container running on macOS:

    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"]
    

    Compile the Java code, build the image and run the container like this:

    $ javac Main.java
    $ docker build -t main .
    $ docker run -p 9010:9010 -it main
    

    Then attach VisualVM using JMX to localhost:9010

    0 讨论(0)
提交回复
热议问题