Eigentlich wollte ich eine Lösung für JEE-Container, speziell für Glassfish, aber nachdem ich viele Kombinationen von Einstellungen ausprobiert hatte und keinen Erfolg hatte, reduzierte ich das Setup auf den einfachsten Fall.
Hier ist mein Hello World-Daemon, der in einem Docker-Container gestartet wurde. Ich möchte anhängen jconsole
oder VisulaVM
daran. Alles ist auf derselben Maschine.
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"]
Gebäude: docker build -t hello-world-daemon .
Laufen: docker run -it --rm --name hwd hello-world-daemon
Fragen:
- Welche JVM-Parameter sollten zur
CMD
Befehlszeile hinzugefügt werden? - Welche Ports sollten verfügbar gemacht und veröffentlicht werden?
- Welchen Netzwerkmodus sollte der Docker-Container verwenden?
Ich zeige meine fehlgeschlagenen Versuche hier nicht, damit die richtigen Antworten nicht verzerrt werden. Dies sollte ein ziemlich häufiges Problem sein, aber ich konnte keine funktionierende Lösung finden.
Aktualisieren. Gearbeitete Lösung
Diese Docker-Datei funktioniert
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 Kombination mit dem Docker-Befehl run
docker run -it --rm --name hwd -p 9010:9010 hello-world-daemon
VisualVM
Die Verbindung wird hergestellt, indem Sie mit der rechten Maustaste auf Lokal-> JMX-Verbindunglocalhost:9010
hinzufügen klicken und dann eingeben oder einen Remote-Host hinzufügen.
JConsole
verbindet sich über die Auswahl eines Remote-Prozesses mit localhost:9010
.
Wenn Sie die Verbindung als remote definieren, kann jede von aufgeführte Schnittstelle ifconfig
verwendet werden. Zum Beispiel funktioniert die docker0
Schnittstelle mit der Adresse 172.17.0.1
. Die Adresse des Containers 172.17.0.2
funktioniert auch.
Cannot connect to localhost:9010 using service:jmx:rmi:///jndi/rmi://localhost:9010/jmxrmi
. Jconsole:Connection failed: error during JRMP connection establishment; nested exception is: java.net.SocketException: Connection reset
Main
Klassennamen in der Befehlszeile angehängt habe . Alle-D
Optionen wurden von stillschweigend ignoriertjava
.-jar foo.jar
werden an die Hauptfunktion der Hauptklasse gesendet (definiert wieMain-Class
im JAR-Manifest); Grundsätzlich sind Argumente vor-jar
für die JVM, Argumente nach-jar
sind für das Programm, das ausgeführt wirdIch folgte einer anderen SO-Antwort auf eine ähnliche Frage und es funktionierte.
Ich habe meinen Java-Prozess im Container gestartet, indem ich die folgenden JVM-Parameter hinzugefügt habe:
-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
und startete den Docker-Container,
-e HOST_HOSTNAME=$HOSTNAME -p <port>
der dendocker run
Befehl angibt .Dann konnte ich von meinem lokalen JVisualVm aus auf diese Remote-Java-App zugreifen, indem ich eine Remote-JMX-Verbindung hinzufügte ("Datei"> "JMX-Verbindung hinzufügen ...") und
<dockerhostname>:<port>
in der Eingabe "Verbindung" spezifizierte und " Keine SSL-Verbindung erforderlich ".quelle
$HOST_HOSTNAME
genau? Ist es ein Host, auf dem Docker ausgeführt wird, oder etwas anderes?hostname
Befehls sein, so dass Sie es an Docker übergeben können, während Sie Ihren Container wie folgt starten:-e HOST_HOSTNAME=`hostname`
Wie von Anthony beantwortet . Ich musste die
-Djava.rmi.server.hostname
Java-Option auf meinem Windows-Computer verwenden.Stellen Sie nur sicher, dass Sie das CMD nicht im JSON-Format in Ihrer Docker-Datei verwenden, da dies keine Shell-Erweiterung unterstützt.
Dockerfile-Beispiel:
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
quelle
FWIW, so konnte ich VisualVM an einen Java-Prozess in einem Docker-Container anhängen, der unter macOS ausgeführt wird:
Main.java:
public class Main { public static void main(String args[]) throws Exception { while (true) { System.out.print("Hello "); System.out.println("world"); Thread.sleep(1000); } } }
Dockerfile:
FROM openjdk:11.0.2-slim COPY Main.class / WORKDIR / ENTRYPOINT ["java", \ "-Dcom.sun.management.jmxremote=true", \ "-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", \ "-Dcom.sun.management.jmxremote.rmi.port=9010", \ "-Djava.rmi.server.hostname=localhost", \ "Main"]
Kompilieren Sie den Java-Code, erstellen Sie das Image und führen Sie den Container folgendermaßen aus:
$ javac Main.java $ docker build -t main . $ docker run -p 9010:9010 -it main
Verbinden Sie dann VisualVM mit JMX mit localhost: 9010
quelle
An alle, die immer noch unter einem Fehler wie dem folgenden leiden:
In meinem Fall habe ich in meinem Docker YML verschiedene Portzuordnungen für die Ports verwendet:
z.B:
15100:9090
Aber anscheinend müssen Sie in Ihren Portbindungen den gleichen Port für den externen Port und den internen Port zuweisen !
Referenz: https://forums.docker.com/t/exposing-mapped-jmx-ports-from-multiple-containers/5287/5
quelle
Vielen Dank an Sie alle, dass Sie mich in die richtige Richtung geleitet haben. Endlich habe ich es in einer komplexeren Konfiguration zum Laufen gebracht: Kubernetes über Docker Desktop unter Windows 10 auf dem lokalen Computer.
Die Konfiguration meiner App:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=30491 -Dcom.sun.management.jmxremote.rmi.port=30491 -Djava.rmi.server.hostname=localhost
Pods Hafen:
ports: - name: jmx containerPort: 30491 protocol: TCP
Port des Dienstes:
ports: - name: jmx nodePort: 30491 port: 9010 protocol: TCP targetPort: jmx
quelle