example - java docker application
Cómo adjunto VisualVM a un proceso simple de Java que se ejecuta en un contenedor Docker (3)
En realidad, quería una solución que funcionara para contenedores JEE, específicamente para Glassfish, pero después de probar muchas combinaciones de configuraciones y no tuve éxito, reduje la configuración al caso más simple posible.
Aquí está mi daemon Hello World iniciado en un contenedor Docker. Quiero adjuntar jconsole
o VisulaVM
a él. Todo está en la misma máquina.
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"]
Edificio: docker build -t hello-world-daemon .
Running: docker run -it --rm --name hwd hello-world-daemon
Preguntas:
- ¿Qué parámetros de JVM deberían agregarse a la línea de comandos de
CMD
? - ¿Qué puertos deberían estar expuestos y publicados?
- ¿Qué modo de red debería usar el contenedor Docker?
No muestro mis intentos fallidos aquí para que las respuestas correctas no sean parciales. Este debería ser un problema bastante común, pero no pude encontrar una solución funcional.
Actualizar. Solución trabajada
Este Dockerfile funciona
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
en combinación con el comando de ejecución del acoplador
docker run -it --rm --name hwd -p 9010:9010 hello-world-daemon
VisualVM
conecta VisualVM
clic con el botón secundario en Local-> Agregar conexión JMX , y luego ingresando localhost:9010
, o agregando un host remoto.
JConsole
conecta seleccionando un proceso remoto con localhost:9010
.
Al definir la conexión como remota, se puede usar cualquier interfaz enumerada por ifconfig
. Por ejemplo, la interfaz docker0
con la dirección 172.17.0.1
funciona. La dirección del contenedor 172.17.0.2
también funciona.
Al principio deberías ejecutar tu aplicación con estos parámetros de JVM:
-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
Entonces debes exponer el puerto para el docker:
EXPOSE 9010
También especifique el enlace del puerto con el comando de ejecución del acoplador:
docker run -p 9010:9010 -it --rm --name hwd hello-world-daemon
Después de eso, puede conectarse con Jconsole al puerto local 9010 y administrar la aplicación que se ejecuta en Docker.
Como respondió Anthony . Tuve que usar la opción java -Djava.rmi.server.hostname
en mi máquina con Windows.
Solo asegúrese de no usar el CMD en formato JSON en su archivo Docker, ya que no es compatible con la expansión del shell.
Ejemplo de Dockerfile:
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
Seguí otra respuesta SO a una pregunta similar y funcionó.
Inicié mi proceso Java dentro del contenedor agregando esos parámetros JVM:
-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
e inició el contenedor Docker especificando -e HOST_HOSTNAME=$HOSTNAME -p <port>
al comando de docker run
del docker run
.
Luego, he podido acceder a esta aplicación Java remota desde mi JVisualVm local al agregar una conexión JMX remota ("Archivo"> "Agregar una conexión JMX ...") y especificar <dockerhostname>:<port>
en el " Conexión "entrada y comprobación" No requiere conexión SSL ".