11

I run the java web application on tomcat in the Docker container.

Is there any way to monitor the memory usage of the java application? I try to use jconsole with the process id of the docker, but it tells me Invalidate process id

I also enable JMX in tomcat, but don't know how to bind to it. I can use visualvm from my local to bind the host machine, but can not find way to bind to the docker inner the host.

Is there any good way to achieve this?

Thanks

Sergei Rodionov
  • 4,079
  • 6
  • 27
  • 44
Browny Lin
  • 2,427
  • 3
  • 28
  • 32
  • 1
    To get the overall memory usage you should be able to monitor the docker container process, right? Not with jconsole, since that is not a Java process, but with Linux tools such as `top`, `ps`, `smem` etc. Or are you talking memory debugging and do you want more detailed information? – qkrijger Apr 16 '14 at 09:16
  • @qkrijger yes, I want to debug the memory leak issue. I know I can run the application locally to do this. Just want to know is there any remote way to achieve this. Thanks – Browny Lin Apr 16 '14 at 09:38
  • 1
    ok, what about running `jconsole` on your host and use http://stackoverflow.com/questions/856881/how-to-activate-jmx-on-my-jvm-for-access-with-jconsole and in Docker expose the jmx remote port? – qkrijger Apr 16 '14 at 13:53

6 Answers6

11

To connect to a java process running in a docker container running in boot2docker with visualvm you can try the following:

Start your java process using the following options:

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=<boot2docker_ip> \
<Main>

You need to run your image with --expose <port> -p <port>:<port>.

Then "Add JMX Connection" in visualvm with <boot2docker_ip>:<port>.

It shouldn't be much different without boot2docker.

Pierre Mage
  • 2,250
  • 1
  • 15
  • 20
  • 2
    Make sure you don't have the option "-Dcom.sun.management.jmxremote.local.only=false" as this was the reason it wasn't working for me. Your answer helped me figure it out. Thanks! – Joao Baltazar Nov 17 '15 at 16:33
3

To monitor it's usage, you need to get it's real Process ID. If you are running tomcat directly in the container, then it should be:

DOCKER_ROOT_PROC=`(docker inspect -f "{{ .State.Pid }}" my_container)`

If you are using something like Phusion's baseimage, then your java process will be a child of that process. To see the hierarchy use:

pstree $DOCKER_ROOT_PROC

Once you have that, you can write your script using

ps -o pid,cmd --no-headers --ppid $DOCKER_ROOT_PROC

In your script recursively to find the java process you want to monitor (with some Regular Expression filtering, of course). Then finally you can use this to get your java application's memory usage in kilobytes:

ps -o vsz -p $JAVAPROCESS

I don't know if this can be used with jconsole, but it is a way of monitoring the memory usage.

coladict
  • 4,799
  • 1
  • 16
  • 27
3

To monitor docker containers I recommend Google's cAdvisor project. That way you have a general solution to monitor docker containers. Just run your app, whatever that is, in a docker container, and check things like cpu and memory usage. Here you have an http API as well as a web ui.

Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
xh3b4sd
  • 865
  • 8
  • 17
0

I tried the Pierre's answer (also answered here) but no way.

At the end I could connect using a SSH tunnel.

Community
  • 1
  • 1
lucasvc
  • 767
  • 1
  • 11
  • 35
0

cAdvisor mentioned above will not help with monitoring Tomcat running inside the container. You may want to take a look at SPM Client docker container, which does exactly that! It has the agents for monitoring a number of different applications running in Docker - Elasticsearch, Solr, Tomcat, MySQL, and so on: https://github.com/sematext/docker-spm-client

user3148164
  • 113
  • 5
0

For the memory usage monitoring of your application in Docker, you can also launch an ejstatd inside your Docker container (calling mvn -Djava.rmi.server.hostname=$HOST_HOSTNAME exec:java -Dexec.args="-pr 2222 -ph 2223 -pv 2224" & from the ejstatd folder before launching your main container process), exposing those 3 ports to the Docker host using docker run -e HOST_HOSTNAME=$HOSTNAME -p 2222:2222 -p 2223:2223 -p 2224:2224 myimage.

Then you will be able to connect to this special jstatd daemon using JVisualVM for example, adding a "Remote Host" specifying your Docker hostname as "Host name" and adding a "Custom jstatd Connections" (in the "Advanced Settings") by setting "2222" to "Port".

Disclaimer: I'm the author of this open source tool.

Anthony O.
  • 22,041
  • 18
  • 107
  • 163