JMX, or Java Management Extensions, is a Java API that allows applications to manage other Java applications. It is used to monitor and control the performance of Java applications, as well as to configure and troubleshoot them.
I have written a post about containerizing a Spring Boot application in my previous post. See 3 Steps to containerize your Spring Boot Application . I’ll write about how to expose the JMX port for this container for monitoring purpose.
I have the following folder structure in my home directory of Docker.
- docker-spring-test
- Dockerfile
- docker-spring-test\target
- docker-test-1.jar
Dockerfile
A Dockerfile is a text file which contains a set of instructions for creating a Docker image. The instructions in a Dockerfile are used to build an image from scratch, or to modify an existing image to create a new one.
FROM openjdk:17
EXPOSE 8080 48080
ARG JAR_FILE=target/docker-test-1.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Dcom.sun.management.jmxremote", "-Dcom.sun.management.jmxremote.port=48080","-Dcom.sun.management.jmxremote.rmi.port=48080","-Dcom.sun.management.jmxremote.ssl=false","-Dcom.sun.management.jmxremote.authenticate=false","-Djava.rmi.server.hostname=192.168.x.y", "-jar", "/app.jar"]
Compared to my previous post, I added a few additional parameters. Those new parameters are given in bold.
Build the Docker image
So, we shall create Docker image first.
$ docker build -t sredigest/docker-spring-jmx-test .
This will take some time. It may produce an output similar to this.
[+] Building 4.6s (8/8) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 369B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:17 2.5s
=> [internal] load .dockerignore 0.2s
=> => transferring context: 2B 0.0s
=> [1/3] FROM docker.io/library/openjdk:17@sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 0.0s
=> [internal] load build context 0.2s
=> => transferring context: 409B 0.0s
=> CACHED [2/3] ADD target/docker-test-1.jar app.jar 0.0s
=> [3/3] ADD management.properties management.properties 0.4s
=> exporting to image 0.4s
=> => exporting layers 0.3s
=> => writing image sha256:29dfb4377826f0862221e752ac980764ae02596174a486af2ee076ae2a6ff493 0.0s
=> => naming to docker.io/sredigest/docker-spring-jmx-test
We list the images
$ docker image ls to verify if the image is created properly. Yes it is.
REPOSITORY TAG IMAGE ID CREATED SIZE
sredigest/docker-spring-jmx-test latest 29dfb4377826 27 seconds ago 491MB
sredigest/docker-spring-test latest e4c747f89a69 33 hours ago 491MB
myorg/myapp latest 7bbeea427bd7 2 days ago 335MB
hello-world latest d2c94e258dcb 9 months ago 13.3kB
Run the container
Next step is to run the container. It exposes to ports. 8080 is the web port. 48080 is the container port.
$ docker run -p 8080:8080 -p 48080:48080 sredigest/docker-spring-jmx-test
Let’s verify if the container is running
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
942bbd8fc058 sredigest/docker-spring-jmx-test "java -Dcom.sun.mana…" 9 minutes ago Up 9 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:48080->48080/tcp, :::48080->48080/tcp sad_raman
Yes it is running. Let’s open the firewall now.
Open the port in Linux firewall
The application is started without any issue. We need to connect to the web port and JMX port from a remote machine. Hence we open it on the server’s firewall. Exposing the JMX ports to remote world is a risky job. Generally you need to expose only to the specific IP from where you will connect JMX port. I exposed it to public for this tutorial.
# firewall-cmd –zone=public –add-port=8080/tcp –permanent
# firewall-cmd –zone=public –add-port=48080/tcp –permanent
# firewall-cmd –reload
Connect with JMX client
You may use tools like jConsole or jVisualVM to connect to JMX now.
—
This post is written as part of #WriteAPageADay campaign of BlogChatter