Подтвердить что ты не робот

Как подключить VisualVM к простому процессу Java, запущенному в контейнере Docker

На самом деле я хотел найти решение для контейнеров JEE, особенно для Glassfish, но после того, как я попробовал много комбинаций настроек и не смог добиться успеха, я уменьшил настройку до самого простого случая.

Вот мой демон Hello World, запущенный в контейнере Docker. Я хочу привязать к нему jconsole или VisulaVM. Все находится на одной машине.

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"]

Здание: docker build -t hello-world-daemon .

Запуск: docker run -it --rm --name hwd hello-world-daemon

Вопросы:

  • какие параметры JVM следует добавить в командной строке CMD?
  • какие порты должны быть опубликованы и опубликованы?
  • какой сетевой режим должен использовать контейнер Docker?

Я не показываю свои неудачные попытки здесь, чтобы правильные ответы не были предвзятыми. Это должно быть довольно распространенной проблемой, но я не мог найти рабочего решения.

Обновить. Рабочее решение

Этот файл Dockerfile работает

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

в сочетании с командой запуска docker

docker run -it --rm --name hwd -p 9010:9010 hello-world-daemon

VisualVM подключается через правый щелчок Local- > Add JMX Connection, а затем вводит localhost:9010 или добавляет удаленный хост.

jconsole подключается через выбор удаленного процесса с помощью localhost:9010.

При определении соединения как удаленного можно использовать любой интерфейс, указанный ifconfig. Например, работает интерфейс docker0 с адресом 172.17.0.1. Адрес контейнера 172.17.0.2 также работает.

4b9b3361

Ответ 1

Сначала вы должны запустить приложение с этими параметрами 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

Затем вы должны открыть порт для докеров:

EXPOSE 9010

Также укажите привязку порта с командой запуска docker:

docker run -p 9010:9010 -it --rm --name hwd hello-world-daemon

После этого вы можете подключиться к Jconsole к локальному порту 9010 и управлять запуском приложения в Docker.

Ответ 2

Я последовал за другим ответом SO на аналогичный вопрос, и он сработал.

Я начал свой Java-процесс внутри контейнера, добавив эти параметры 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

и запустил контейнер Docker, указав -e HOST_HOSTNAME=$HOSTNAME -p <port> в команду docker run.

Затем я смог получить доступ к этому удаленному Java-приложению из своего локального JVisualVm, добавив удаленное соединение JMX ( "Файл" > "Добавить соединение JMX..." ) и указав <dockerhostname>:<port> в "Подключение" ввод и проверка "Не требуется SSL-соединение".

Ответ 3

Как ответил Anthony. Я должен был использовать параметр -Djava.rmi.server.hostname java на моей машине Windows.

Просто не забудьте использовать CMD в формате JSON в файле Docker, так как это не поддерживает расширение оболочки.

Пример файла 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