Search code examples
javadockerjmx

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


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 to the simplest possible case.

Here is my Hello World daemon started in a Docker container. I want to attach jconsole or VisulaVM to it. Everything is on the same machine.

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

Building: docker build -t hello-world-daemon .

Running: docker run -it --rm --name hwd hello-world-daemon

Questions:

  • what JVM parameters should be added to CMD command line?
  • what ports should be exposed and published?
  • what network mode should Docker container be using?

I do not show my failed attempts here so that correct answers will not be biased. This should be a pretty common problem, yet I could not find a working solution.

Update. Worked solution

This Dockerfile works

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

in combination with the docker run command

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

VisualVM connects via right click Local->Add JMX Connection, and then entering localhost:9010, or through adding a remote host.

JConsole connects via selecting a Remote process with localhost:9010.

When defining the connection as remote, any interface listed by ifconfig can be used. For instance, docker0 interface with address 172.17.0.1 works. The container's address 172.17.0.2 works too.


Solution

  • 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.