Докер здесь, Докер там, я вижу докеров везде
В этом посте я опишу процесс переноса приложения 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: 8 MAINTAINER email @example .com VOLUME /tmp EXPOSE 8080 ENV USER_NAME blogger ENV APP_HOME /home/$USER_NAME/app RUN useradd -ms /bin/bash $USER_NAME RUN mkdir $APP_HOME ADD jvm-bloggers- 0.5 . 0 .jar $APP_HOME/jvm-bloggers.jar RUN chown $USER_NAME $APP_HOME/jvm-bloggers.jar 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" ] |
Итак, позвольте мне объяснить этот файл шаг за шагом:
- ОТ 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 FAILED FAILURE: 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 SIZE tdziurko/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 login Username: tdziurko Password: Email: tomek @example .com WARNING: login credentials saved in /Users/tomek/.docker/config.json Login 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 . |