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.

  • How to debug seg fault in docker container?
  • How to skip a gradle task under some cases, which introduced by the bmuschko/gradle-docker-plugin?
  • Run 'docker volume create' with Ansible?
  • 502 Bad Gateway nginx/1.11.5 running inside docker
  • Pip installs within Docker container : Locally vs Remotely
  • Docker run github branch/pull request
  • 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.

  • Run Hadoop with Docker (for both DEV and PROD environments)
  • docker-compose : Unsupported config option for services service: 'web'
  • python2 interpreter in Docker does not support remote project creation with PyCharm
  • Docker error FATA[0000] on debian
  • How to use docker remote api to create a container using another container's network namespace
  • Docker container cannot resolve hosts
  • 2 Solutions collect form web for “How do I attach VisualVM to a simple Java process running in a Docker container”

    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.

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

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.