0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: docker, java, программирование на java, разработка на java, java 10, контейнер</p>
1
<p>Теги: docker, java, программирование на java, разработка на java, java 10, контейнер</p>
2
<p>Сейчас Java всё чаще используется в контейнерах, обычно в<strong>Docker</strong>. Формально в Docker можно положить любую версию Java, и это даже как-то будет работать. Однако когда вышла<strong>Java 8</strong>, про работу в Docker ещё никто и не думал. В результате<strong>Java-приложение</strong>хоть и работает,<strong>но не понимает</strong>, что находится в ограниченном окружении.<strong>Не видит ограничение Docker-а</strong>на использование процессора и памяти.</p>
2
<p>Сейчас Java всё чаще используется в контейнерах, обычно в<strong>Docker</strong>. Формально в Docker можно положить любую версию Java, и это даже как-то будет работать. Однако когда вышла<strong>Java 8</strong>, про работу в Docker ещё никто и не думал. В результате<strong>Java-приложение</strong>хоть и работает,<strong>но не понимает</strong>, что находится в ограниченном окружении.<strong>Не видит ограничение Docker-а</strong>на использование процессора и памяти.</p>
3
<p>Это приводит к весьма неприятным последствиям. Например,<strong>приложение не учитывает ограничение на процессоры</strong>и может создавать пулы с большим количеством потоков или не видит ограничение по памяти и неожиданно закрывается Docker-ом при превышении лимита.</p>
3
<p>Это приводит к весьма неприятным последствиям. Например,<strong>приложение не учитывает ограничение на процессоры</strong>и может создавать пулы с большим количеством потоков или не видит ограничение по памяти и неожиданно закрывается Docker-ом при превышении лимита.</p>
4
<p>Работа в контейнере начала улучшаться, начиная c<strong>Java 9</strong>(есть и обратные порты в Java 8), в релизе<strong>Java 10</strong>был добавлен новый параметр UseContainerSupport. Этот параметр сообщает<strong>Java-приложению</strong>, что оно запущено в контейнере и необходимо учитывать наложенные ограничения, а не использовать все ресурсы операционной системы без ограничений.</p>
4
<p>Работа в контейнере начала улучшаться, начиная c<strong>Java 9</strong>(есть и обратные порты в Java 8), в релизе<strong>Java 10</strong>был добавлен новый параметр UseContainerSupport. Этот параметр сообщает<strong>Java-приложению</strong>, что оно запущено в контейнере и необходимо учитывать наложенные ограничения, а не использовать все ресурсы операционной системы без ограничений.</p>
5
<p>Давайте посмотрим, как это работает. По умолчанию UseContainerSupport включён, т. е. приложение видит ограничения контейнера. Положим в контейнер простое приложение, которое выводит количество доступных процессоров:</p>
5
<p>Давайте посмотрим, как это работает. По умолчанию UseContainerSupport включён, т. е. приложение видит ограничения контейнера. Положим в контейнер простое приложение, которое выводит количество доступных процессоров:</p>
6
Runtime.getRuntime().availableProcessors().<p>Соберём образ и запустим контейнер такой командой:</p>
6
Runtime.getRuntime().availableProcessors().<p>Соберём образ и запустим контейнер такой командой:</p>
7
docker run --memory=100m --cpus 2 java-docker<p>Вводим ограничение для контейнера: память 100 Мб и 2 процессора. В контейнере запускается такая команда:</p>
7
docker run --memory=100m --cpus 2 java-docker<p>Вводим ограничение для контейнера: память 100 Мб и 2 процессора. В контейнере запускается такая команда:</p>
8
CMD java -XX:+PrintFlagsFinal -version | grep MaxHeapSize<p>Получаем результат:</p>
8
CMD java -XX:+PrintFlagsFinal -version | grep MaxHeapSize<p>Получаем результат:</p>
9
size_t MaxHeapSize = 52428800<p>Это примерно 52 Мб, т. е. примерно половина лимита контейнера.Теперь посмотрим на доступные процессоры:</p>
9
size_t MaxHeapSize = 52428800<p>Это примерно 52 Мб, т. е. примерно половина лимита контейнера.Теперь посмотрим на доступные процессоры:</p>
10
CMDjava -jartestJavaAppl.jar<p>Возвращает:</p>
10
CMDjava -jartestJavaAppl.jar<p>Возвращает:</p>
11
Runtime.getRuntime().availableProcessors(): 2<p>Видим, что Java-приложение учитывает в своей работе лимиты, заданные контейнером. Давайте повторим эксперимент, но на этот раз отключим режим UseContainerSupport - это<strong>фактически вернёт нас во времена Java 8</strong>. Ограничения контейнера те же. Смотрим память:</p>
11
Runtime.getRuntime().availableProcessors(): 2<p>Видим, что Java-приложение учитывает в своей работе лимиты, заданные контейнером. Давайте повторим эксперимент, но на этот раз отключим режим UseContainerSupport - это<strong>фактически вернёт нас во времена Java 8</strong>. Ограничения контейнера те же. Смотрим память:</p>
12
CMD java -XX:-UseContainerSupport -XX:+PrintFlagsFinal -version | grep MaxHeapSize<p>Получаем:</p>
12
CMD java -XX:-UseContainerSupport -XX:+PrintFlagsFinal -version | grep MaxHeapSize<p>Получаем:</p>
13
size_tMaxHeapSize = 8415870976<p>Java не видит ограничение в 100 Мб и пытается использовать память "на всю котлету". А теперь смотрим, что происходит с процессором:</p>
13
size_tMaxHeapSize = 8415870976<p>Java не видит ограничение в 100 Мб и пытается использовать память "на всю котлету". А теперь смотрим, что происходит с процессором:</p>
14
CMD java -XX:-UseContainerSupport -jar testJavaAppl.jar<p>Получаем:</p>
14
CMD java -XX:-UseContainerSupport -jar testJavaAppl.jar<p>Получаем:</p>
15
Runtime.getRuntime().availableProcessors(): 12<p>И по процессорам Java пытается использовать все системные ресурсы, игнорируя ограничения Docker-а. Очевидно, что для корректной работы Java-приложения в Docker-е желательно использовать версию<strong>Java 10</strong>или новее.</p>
15
Runtime.getRuntime().availableProcessors(): 12<p>И по процессорам Java пытается использовать все системные ресурсы, игнорируя ограничения Docker-а. Очевидно, что для корректной работы Java-приложения в Docker-е желательно использовать версию<strong>Java 10</strong>или новее.</p>
16
<p>В следующей заметке затронем другие аспекты работы<strong>Java-приложения в контейнере</strong>. А более подробно посмотрим на это дело на открытом вебинаре "<a>Java и Docker</a>".</p>
16
<p>В следующей заметке затронем другие аспекты работы<strong>Java-приложения в контейнере</strong>. А более подробно посмотрим на это дело на открытом вебинаре "<a>Java и Docker</a>".</p>
17
17