Подводный камень в docker env и java

в 4:16, , рубрики: apache maven, build, docker, environment variables, example, java, multistage, spring boot, web, микросервисы

Добрый день, уважаемые читатели!

Столкнулся с небольшим с интересным моментом: внедрение переменных окружения (а ля environment variables) в стандартный микросервис написанный на Java (классика жанра – Spring Boot). Уверен тема не сложная, но столкнулся с одним не очевидным для меня некоторыми подводным камнем, про которые хотел бы поделиться с вами.

Зачастую при разработке у вас могут появиться десятки, а в некоторых проектах и сотни настроек для одного сервиса. Нередки случаи изменения какого-нибудь параметра приложения (например, порта сервера или подключения к базе данных) и не хотелось бы производить rebuild (сборку) проекта, который может длиться относительно долго. Отличным вариантом служит – вынести параметр приложения в application.properties или application.yml в рамках разработки с использованием Spring Boot. А также позволяет отделить настройки от кода и легко адаптировать приложение для разных окружений.

При работе с Apache Maven мы можем получить в результате сборки application.jar (далее jar-файл), а после запросто запустить (при условии pom.xml, верно, настроен) приложение.  Стоит отметить при использовании инструмента контейнеризации – Docker, который обладает возможностью задать переменных окружения (environment variables), мы получаем более гибкую настройку над приложением.

Цель данной статьи раскрыть некоторые тонкости настройки переменных окружения.

Скрытый текст

Вероятно, для более опытных разработчиков это может показаться простым и они могут закрыть статью на данном моменте

Для начала кратко опишу приложение:

  • Основной фреймворк: Spring Boot

  • Инструмент для автоматической сборки: Apache Maven

  • Инструмент для контейнеризации: Docker

В общем и целом, простое MVC веб-приложение. Ссылка на репозиторий.
Основные три файла приложения (в рамках статьи) представлены на изображении (рис.1):

Рис.1 – Основные три файла приложения

Рис.1 – Основные три файла приложения

Исходя из рис.1 в приложении две настройки – порт сервера(server.port) и сообщение(application.my.variable). Параметр application.my.variable передается в EnvStorageService в качестве поля. Рекомендуется использовать следующую структуру, которую легко распознает Docker: ${НАЗВАНИЕ_ПАРАМЕТРА:значение по умолчанию}. Как указано в application.properties (файл со свойствами приложения) server.port=8085. Убедимся в этом если запустим пробный вариант через localhost:8085 (рис.2):

Рис.2 – Пробный вариант запуска приложения

Рис.2 – Пробный вариант запуска приложения

Итак, мы получили "HELLO FROM APPLICATION", которое мы указали в конфигурационном файле по умолчанию (application.properties) и получили данные через 8085-ый порт.

Dockerfile – можно представить из двух частей. Dockerfile приставлен на рис. 3.

  1. build. Сборка посредством Apache Maven, в результате сборки получаем example.jar

  2. stage-1. запуск JAR-file

В красных рамочках объявлены переменные окружения для соответствующих stages.

Рис.3 – Dockerfle приложения

Рис.3 – Dockerfle приложения

Запустим сборку образа Docker и откроем логи (рис.4):

Рис.4 – Логи сборки Dockerfule для соответствующих stage

Рис.4 – Логи сборки Dockerfule для соответствующих stage

Исходя из рис. 4, мы видим, что переменные среды успешно внедрились в образ, но только какой набор будет актуальный при запуске приложения?

Предполагается, что при stage build в корне JAR-файла будут именно внедрены 8086 и "HELLO FROM BUILD STAGE":

Рис.5.1 – Запуск build stage

Рис.5.1 – Запуск build stage
Рис. 5.2 – Результат запуска build stage

Рис. 5.2 – Результат запуска build stage

Исходя из рисунков 5.1– 5.2, успешно внедрились параметры из build(см. рис. 3) при сборке только build stage. Но если мы уберем переменные среды из stage-1, то в результате полная multistage сборка не совершиться.

Совершим запуск из stage-1 (что рекомендуется в будущем), который представлен на рисунке 6.

Рис. 6 – Результат запуска stage-1

Рис. 6 – Результат запуска stage-1

В результате получаем "HELLO FROM RUNNIG STAGE" (очепятка) на порту 8087. При запусках всех образов я пробрасывал маппинг портов указанный в Dockerfile(-p 8086:8086 и -p 8087:8087).

Заключение

В результате имеем, что можем задавать отдельные переменные окружения в каждый stage сборки Dockerfile. Данная особенность позволяет гибче настроить тесты при сборке приложения (build) и уже на запуске собранного приложения указать абсолютно другие настройки.

Буду рад услышать конструктивную критику и пожелания. Надеюсь, информация из статьи пригодиться в будущем.

Автор: rusia2054

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js