Докер здесь, Докер там, я вижу докеров везде
В этом посте я опишу процесс переноса приложения Spring Boot в Docker. Мы начнем с изменения файла сборки, затем создадим Dockerfile, чтобы он мог запускаться локально. Наконец мы опубликуем наше изображение в DockerHub .
Вступление
Несколько месяцев назад я начал новый личный проект под названием JVM Bloggers с целью помочь польским программистам распространять новости о своих новых постах в блоге. Первоначально это приложение Spring Boot было размещено на моей локальной машине, затем я перенес его в бесплатный аккаунт на Heroku .
И в первые недели я был удовлетворен: приложение не должно быть подключено к Интернету 24 часа в сутки, поэтому сон в течение 8 часов в день (ограничение бесплатной учетной записи Heroku) не был большой проблемой, ограничение памяти в 500 МБ меня тоже не ограничивало. Но по мере роста блоггеров JVM у меня возникали странные проблемы с использованием памяти: приложение начинало использовать 500-550 МБ, и было очень трудно найти источник такого поведения. Я даже оставил приложение запущенным на моей локальной машине с подключенным профилировщиком, но все еще не нашел ничего подозрительного.
Проблемы с объемом памяти стали раздражать, так как мне приходилось следить за приложением и перезапускать его каждые 1-2 дня, и из-за природы Heroku я не мог просто подключиться к серверу через ssh и отладить или подключить профилировщик к запущенному процессу. Стало ясно, что если я собираюсь добавить больше функций в блоггеры JVM, мне нужно перенести их на что-то более гибкое — машину Linux с Docker.
докер
В настоящее время Docker является очень популярной темой среди многих разработчиков, особенно в проектах, переходящих на архитектуру микросервисов. Но наиболее интересной особенностью с точки зрения моей проблемы является возможность создавать стандартизированный образ моего приложения и запускать его в других средах, не беспокоясь о различиях. Один образ можно развернуть либо локально, либо практически на любой машине с Linux, поэтому с помощью Docker я смог бы протестировать свое приложение локально, развернуть его на AWS или где-то еще без особых хлопот.
миграция
Сначала мы должны добавить некоторые новые зависимости и задачи в наш скрипт build.gradle :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
buildscript { // ... dependencies { // ... classpath('se.transmode.gradle:gradle-docker:1.2') }}// ...group = 'tdziurko' // this will be my login at DockerHub (more about it later in this post)task buildDocker(type: Docker, dependsOn: build) { // this task will build our Docker image push = true applicationName = jar.baseName dockerfile = file('src/main/docker/Dockerfile') doFirst { copy { from jar into stageDir } }} |
В строке 17 мы указали местоположение нашего Dockerfile, так что теперь пришло время создать его там.
Создание Dockerfile
Dockerfile — это файл конфигурации, который определяет, как создать наш образ Docker, который мы можем развернуть позже.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
FROM java:8MAINTAINER email@example.comVOLUME /tmpEXPOSE 8080ENV USER_NAME bloggerENV APP_HOME /home/$USER_NAME/appRUN useradd -ms /bin/bash $USER_NAMERUN mkdir $APP_HOMEADD jvm-bloggers-0.5.0.jar $APP_HOME/jvm-bloggers.jarRUN chown $USER_NAME $APP_HOME/jvm-bloggers.jarUSER $USER_NAMEWORKDIR $APP_HOMERUN bash -c 'touch jvm-bloggers.jar'ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","jvm-bloggers.jar"] |
Итак, позвольте мне объяснить этот файл шаг за шагом:
- ОТ java: 8 : наше базовое изображение, это что-то вроде ключевого слова extension в Java. Здесь мы хотим опираться на образ с установленной Java 8
- VOLUME / tmp : смонтированный каталог, в котором наше приложение может записать что-либо на диск
- EXPOSE 8080 : номер порта, наше приложение будет запущено, оно будет доступно снаружи контейнера Docker
- ENV USER_NAME blogger : вспомогательная переменная с именем пользователя, которое мы будем использовать для запуска нашего приложения
- ENV APP_HOME / home / $ USER_NAME / app : следующая вспомогательная переменная с каталогом, в котором будет находиться наше приложение
- RUN useradd -ms / bin / bash $ USER_NAME : создать пользователя с именем, определенным в $ USER_NAME
- RUN mkdir $ APP_HOME : создать каталог приложения
- ДОБАВИТЬ jvm-bloggers-0.5.0.jar $ APP_HOME / jvm-bloggers.jar : добавить fat-jar к нашему изображению и поместить его в $ APP_HOME
- RUN chown $ USER_NAME $ APP_HOME / jvm-bloggers.jar : все предыдущие команды были выполнены как ROOT, поэтому нам нужно изменить владельца нашего jar-файла на $ USER_NAME . Обычно использование ROOT в Docker считается неправильным подходом из-за безопасности.
- USER $ USER_NAME; WORKDIR $ APP_HOME : измените пользовательский и рабочий каталог на те, которые мы хотим использовать для запуска нашего приложения
- RUN bash -c ‘touch jvm-bloggers.jar’ : коснитесь нашего файла, чтобы у него было время модификации
- ENTRYPOINT [«java», «- Djava.security.egd = file: / dev /./ urandom», «- jar», «jvm-bloggers.jar»] : выполнить наш fat-jar (urandom для источника Tomcat энтропия)
Запуск образа Docker локально
Теперь у нас есть все для сборки и запуска нашего образа Docker.
|
1
|
./gradlew clean build buildDocker |
Отклик:
|
1
2
3
4
5
6
7
8
9
|
:buildDocker FAILEDFAILURE: Build failed with an exception.* What went wrong:Execution failed for task ':buildDocker'.> Docker execution failed Command line [docker push tdziurko/jvm-bloggers:latest] returned: unauthorized: access to the requested resource is not authorized |
Не удалось выполнить задачу buildDocker, так как у вас нет учетной записи на DockerHub или вы не вошли в систему. но если вы проверите местные изображения
|
1
|
docker images |
Вы увидите, что наше изображение с тегом последней готово к использованию:
|
1
2
|
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEtdziurko/jvm-bloggers latest a09f884c5aa9 11 minutes ago 785.6 MB |
Таким образом, мы можем запустить его в контейнере Docker с помощью следующей команды:
|
1
|
docker run -p 8080:8080 --add-host=database:<your_local_db_host> -e jasypt.encryptor.password="<secretPassword>" -e spring.profiles.active="dev" tdziurko/jvm-bloggers:latest |
Опять же, некоторые фрагменты требуют более подробного объяснения:
- —Add-host = database: <your_local_db_host> : добавляет адрес в / etc / hosts в контейнере, база данных var должна быть адресом нашей базы данных, например, 192.168.0.101
- -e jasypt.encryptor.password = « »: пароль Jasypt для расшифровки некоторых значений из файлов * .properties, -e добавляет его в качестве переменной env в контейнер
- -e spring.profiles.active = «dev» : профиль весенней загрузки. dev используется для локального запуска приложения
Через несколько секунд вы увидите, что наше приложение запущено и работает в контейнере Docker.
Публикация в DockerHub
Наличие образа Docker, доступного локально, — это нормально, если вы планируете играть с ним только на своем компьютере, но, поскольку мы стремимся к развертыванию AWS, нам нужно опубликовать наш образ в DockerHub, чтобы он был доступен с любого компьютера Linux.
Сначала нужно создать учетную запись там (в моем случае это tdziurko ) и войти в систему с помощью клиента Docker, чтобы мы могли опубликовать его.
|
1
2
3
4
5
6
|
$ docker loginUsername: tdziurkoPassword:Email: tomek@example.comWARNING: login credentials saved in /Users/tomek/.docker/config.jsonLogin Succeeded |
Теперь мы можем перестроить наше приложение для отправки изображения в DockerHub:
|
1
|
./gradlew clean build buildDocker |
Через несколько минут мы увидим сообщение BUILD SUCCESSFUL, и если вы зайдете на страницу общедоступного профиля DockerHub, вы увидите нечто похожее:
Это означает, что наш образ Docker с приложением находится в ожидании развертывания на машине AWS EC2. Но это материал для другого поста в блоге 🙂
Резюме
В нескольких шагах я описал, как добавить возможности Docker в ваш проект Java, как настроить изображение и опубликовать его в DockerHub. Весь процесс не очень сложен, и давайте подготовим приложение к развертыванию на каждом компьютере Linux или сервере, поддерживающем Docker.
| Ссылка: | Dockerizing Spring Boot Application от нашего партнера JCG Томаша Дзюрко в блоге Code Hard Go Pro . |
