Код
#База знаний

Как разместить Spring-Boot-приложение на heroku.com. Пошаговая инструкция

Написали код, всё протестировали, и теперь у вас есть рабочее приложение на Spring? Не дайте ему запылиться на жёстком диске!

1. Прежде чем начать работу

Чтобы опубликовать приложение, вам потребуются:

  • аккаунт на облачной платформе Heroku — просто зарегистрируйтесь;
  • репозиторий с вашим проектом Spring + Мaven. Это необходимо, чтобы проект находился в отдельном репозитории, в корне которого есть файл pom.xml. Подходят любые репозитории, включая приватные;
  • банковская карта для активации Add-ons, таких как MySQL или PostgreSQL, — требуется даже для бесплатных тарифов.

📌  Heroku запускает ваше приложение в лёгких изолированных контейнерах Linux, которые называются dynos. Платформа предлагает различные типы дино, оптимизированные для разных приложений. У всех бесплатных dynos есть ограничения, о которых нужно помнить:

  • Add-on ClearDB допускает не более 3 600 запросов к базе данных в час.
  • Всего 550–1000 бесплатных часов активности контейнеров в месяц. Да, это примерно 41 день работы, но время делится на все ваши приложения, созданные на аккаунте.
  • Если бесплатные часы активности исчерпаны, приложение после тридцати минут бездействия «засыпает». Когда вы снова зайдёте по адресу «спящего» приложения, потребуется одна-две минуты, чтобы оно ответило.
  • Максимум 512 МБ оперативной памяти на контейнер.

2. Создаём новое приложение

Зайдите в личный кабинет и в правом верхнем меню нажмите New → Create new app.

Введите имя вашего приложения — имя станет частью URL для доступа к нему, а затем нажмите Create app. Живущим в европейской части России рекомендую выбирать регион Европа — дата-центр с сервером приложений окажется ближе к вам, и время отклика будет меньше.

Например, созданное мной приложение с именем shibkov-java-skillbox будет в дальнейшем доступно по адресу https://shibkov-java-skillbox.herokuapp.com/.

Теперь, когда у нас есть приложение, самое время настроить окружение для работы с Heroku в операционной системе — установить консольную утилиту heroku. Это универсальный метод для работы с приложениями, их запуска и чтения логов.

3. Устанавливаем утилиту heroku-cli

Дистрибутивы, а также краткая инструкция для каждой операционной системы находятся по адресу https://devcenter.heroku.com/articles/heroku-cli. После завершения установки запустите свой любимый эмулятор терминала и выполните команду:

heroku  --version

Если вы, как и я, работаете в Windows 10, то на выходе вы должны увидеть похожий ответ с версией heroku.

Но если что-то пошло не так и команда выдаёт ошибки, посмотрите раздел https://devcenter.heroku.com/articles/heroku-cli#troubleshooting — там есть решения для многих известных проблем.

4. Авторизуемся в сервисе Heroku с помощью клиентского приложения

Теперь самое время авторизоваться на heroku.com через консольную утилиту. Наберите в терминале:

heroku login

Процесс происходит через веб, поэтому нажатием любой клавиши перейдите в ваш браузер по умолчанию или, если решили отказаться, нажмите q для выхода.

Когда откроется браузер, потребуется ввести логин и пароль. А если вы уже были авторизованы в heroku.com, то останется только подтвердить действие и нажать Log in.

Затем можно просто вернуться в терминал — вы увидите, что успешно залогинились в консольном приложении.

Чтобы проверить, кто сейчас авторизован в системе, используйте команду:

heroku auth:whoami

Ответом на неё будет email текущего пользователя. Если на этом этапе всё ок, можно посмотреть список приложений. Как вы помните, одно мы только что уже создали. Проверим, на месте ли оно:

heroku apps

Да, всё в порядке, и ответ системы это подтверждает.

5. Создаём Add-on для работы с MySQL/Postgres

Если ваше приложение использует файловую базу данных или не использует БД вообще, этот шаг вы можете пропустить.

📌  На этом этапе потребуется ввести данные вашей банковской карты. Деньги не будут списаны, пока вы пользуетесь бесплатным тарифом и не превышаете лимиты. Этого более чем достаточно для демонстрации работы приложения и обучения, но для серьёзной работы придётся подписаться на один из платных тарифов Heroku.

Откройте список ваших приложений и зайдите в панель управления приложения, которое мы недавно создали. Затем перейдите в закладку Resources и в поле ввода Add-ons наберите mysql. Если планируете работать с движком MySQL, найдите в списке ClearDB MySQL, а если с Postgres — Heroku Postgres.

Бесплатный тариф здесь называется Ignite — Free. Выберите его. После подтверждения вас попросят ввести данные банковской карты.

Когда введёте информацию о банковской карте, снова перейдите в Add-ons и создайте базу данных ClearDB — в окне выбора тарифа нажмите Provision. После этого в вашем списке Add-ons появится эта новая БД. Теперь самое время попробовать подключиться к ней и задать структуру.

6. Настраиваем подключение к базе данных

Откройте настройки Settings вашего приложения:

В разделе Config Vars нажмите кнопку Reveal Config Vars — откроется список переменных конфигурации.

Сейчас нас интересует переменная CLEARDB_DATABASE_URL, в которой содержится строка-ссылка для доступа к БД с указанием логина, пароля и других параметров подключения.

Рассмотрим подробнее эту строку и её составляющие:

mysql://b04d2ddd4273f2:63623d8c@eu-cdbr-west 02. cleardb.net/heroku_b72e9b34372c084? reconnect=true

Здесь в строке уже есть протокол, имя пользователя, пароль и хост, где находится наша база данных. Параметры упакованы в эту строковую переменную по схеме:

[protocol://][user[: [password]]@]host[: port][/schema][? attribute1=value1.]

📌  Подробнее о том, как это работает, можно почитать в разделе «Подключение к серверу с помощью строк типа URI или пар „ключ-значение“» официальной документации по MySQL 8.0.

Чтобы наше приложение и БД работали в кодировке UTF, необходимо после знака вопроса добавить в строку подключения (через амперсанд) следующие параметры: useUnicode=true, characterEncoding=utf-8, reconnect=true.

В итоге должно получиться следующее:

mysql://b04d2ddd4273f2:63623d8c@eu-cdbr-west-02.cleardb.net/heroku_b72e9b34372c084? useUnicode=true& characterEncoding=utf-8& reconnect=true

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

📌  Неплохой выбор утилиты для работы с БЗ — community-версия DBeaver. Она совершенно бесплатна и есть для всех ОС.

На этом этапе и далее запускайте утилиту с параметром reconnect=true, как показано на скриншоте. Чтобы проверить, правильно ли настроен драйвер, просто нажмите Test Connection. Вы должны получить примерно такое сообщение в модальном окне.

В том случае, если ваше приложение не должно самостоятельно создавать структуру БД, придётся это сделать вручную. Также не забудьте перенести в БД на Heroku дамп тестовых данных. После этих операций база готова, мы можем использовать её для дальнейшей работы.

7. Настраиваем Java-Spring-приложение

Теперь добавим в наше Java-Spring-приложение настройки, необходимые для его отправки и запуска в контейнере Heroku.

📌  Все дальнейшие действия будут показаны на примере операционной системы Windows. На других ОС всё очень похоже, потому что мы везде используем консольную утилиту heroku cli.

Для примера я взял одну из дипломных работ студентов курса «Профессия Java-разработчик». Ваши файлы с параметрами могут немного отличаться, но все остальные настройки будет примерно такими же.

Клонируйте ваш репозиторий и/или откройте проект в IDE — на скриншотах примера показана работа с IntelliJ IDEA Community 2020. Проект должен находиться в корне репозитория.

Первое, что нужно сделать, — добавить в файл конфигурации application.properties наши настройки параметров базы данных и номер порта веб-сервера, по которому приложение будет доступно в браузере. Если его не указать, Heroku назначит порт при запуске проекта самостоятельно.

Пример расположения файлов проекта

Откройте application.properties. Сейчас там такой код:

spring.datasource.url=jdbc:mysql://localhost:3306/blog_engine
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

Добавьте параметры в формате ${Имя_Параметра:Значение_по_умолчанию} для spring.datasource.url и server.port, если их там не было:

spring.datasource.url=jdbc:${CLEARDB_DATABASE_URL:mysql://localhost:3306/blog_engine}
server.port=${PORT:8080}

Если коротко, такая запись означает, что, если в параметрах запуска присутствует параметр PORT, следует использовать его либо применить значение по умолчанию — 8080. Для переменной spring.datasource.url настройка параметра CLEARDB_DATABASE_URL работает таким же образом — в локальном окружении и в контейнере Heroku. Мы можем открыть наш проект локально c MySQL на порту 3306, а при деплое будут использоваться параметры, передаваемые приложению в строке запуска.

Проверьте, что всё написано верно, и передайте в параметрах строку доступа к созданной нами БД. Для этого откройте параметры запуска приложения, выбрав в меню Run → Edit Configurations… Или выберите на панели инструментов:

Если у вас пока нет ни одной готовой конфигурации, создайте новую или просто запустите приложение. Подойдёт даже неудачный запуск — конфигурация появится в любом случае.

Допишите параметры запуска приложения в поле Environment variables. Удобно зайти в список (кнопка в конце поля, отмеченная на скриншоте) и там ввести значения, если их несколько.

Введите параметр доступа к БД:

📌  Не забудьте, что логин и пароль уже есть в строке соединения, поэтому отдельные строки данных, прописанные в конфигурации, не используются. Копируйте только ту строку, которую сгенерировал вам Heroku в параметрах Config Vars. Номер порта для тестового запуска менять не нужно.

Теперь попробуйте запустить приложение. Если дамп был загружен на Heroku и у него верная структура, то ваша программа будет работать локально, но использовать при этом облачную БД.

После успешного запуска переходите к следующему этапу.

8. Тестируем публикацию приложения и читаем лог

Облако Heroku каждый раз собирает приложение из исходников с помощью Maven и выполняет полученный jar в своём окружении. Для запуска приложений в контейнерах Heroku используется команда mvn install.

Чтобы понять, что происходит в облаке, и научиться делать настройки более осознанно, попробуем отправить наше тестовое приложение в Heroku и развернуть. Для этого выполним следующие шаги:

  • Откроем папку с репозиторием проекта в терминале Git Bash.
  • Найдём ссылку на удалённый репозиторий heroku для вашего приложения в Settings — в разделе App Information → Heroku git URL.
  • Добавим новый удалённый репозиторий к вашему Git.
git remote add heroku https://git.heroku.com/shibkov-java-skillbox.git

Далее запустим команду git push heroku — в репозиторий heroku будет выполнена попытка сборки и публикации вашего приложения.

📌  На скриншоте видно, что попытка развернуть приложение проходит с использованием JDK 1.8. Если у вас есть конструкции из JDK 11, этот параметр надо обязательно установить, а не использовать по умолчанию.

Я отметил цветом, что используется Maven 3.6.2, который собирает проект командой install, пропуская при этом тесты. Но проект не соберётся, если не был настроен Maven, и мы увидим такое окончание запуска:

Неудача вполне ожидаема. Зато мы получили все необходимые данные для исправления ошибок и дальнейшей работы: необходимо правильно настроить ресурсы для сборки приложения, установить версию JDK для компиляции.

Приступим!

9. Настраиваем версию JDK для Heroku

Чтобы настроить версию JDK, создайте в корне проекта файл system.properties с таким содержимым:

java.runtime.version=11

Добавьте файл в git и выполните коммит, не забыв закоммитить ранее изменённый application.properties. После этих действий снова выполните push на Heroku.

git push heroku

В результате вы увидите, что контейнер Heroku подхватил эти настройки и использует JDK11.

И даже сборка будет успешной:

Но только на первый взгляд — перейдя по ссылке деплоя, мы увидим Application Error. Это означает, что приложение завершилось с ошибкой и сборка приложения выполнена неверно. Самое время её настроить.

10. Готовим Maven для сборки

Для настройки измените файл pom.xml. При исполнении Maven прежде всего проверяет, есть ли в нём все необходимые данные и все ли они синтаксически правильно записаны. Ниже мой пример, а ваши значения, скорее всего, будут другими.

<groupId>skillbox-java-course</groupId>
<artifactId>blog-engine</artifactId>
<version>1.0</version>

Эти настройки говорят, что при сборке будет создан файл с именем blog-engine-1.0.jar в папке target. Формула сборки имени файла такая: [artifactId]-[version].jar. Запомните её — нам это пригодится в дальнейшем.

📌  Папка target должна быть исключена из отслеживания Git.

Теперь добавьте настройки плагина сборки, поместив в блок properties файла pom.xml такие строки:

<properties>
  <java.version>11</java.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <maven.compiler.source>11</maven.compiler.source>
  <maven.compiler.target>11</maven.compiler.target>
</properties>

И в блок build:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
          <executions>
            <execution>
              <goals>
                <goal>build-info</goal>
              </goals>
              <configuration>
                <additionalProperties>
                  <encoding.source>${project.build.sourceEncoding}</encoding.source>
                  <encoding.reporting>${project.reporting.outputEncoding}</encoding.reporting>
                  <java.source>${maven.compiler.source}</java.source>
                  <java.target>${maven.compiler.target}</java.target>
                </additionalProperties>
              </configuration>
            </execution>
          </executions>
      </plugin>
   </plugins>
</build>

Затем создайте в корне проекта файл Procfile (без расширения) с таким содержанием:

web: java -jar target/blog-engine-1.0.jar

Здесь мы объясняем Heroku, как запустить приложение. Поэтому поменяйте имя файла на имя вашего артефакта и версию. В итоге проект с новыми файлами будет выглядеть так:

11. Публикуем приложение

Добавьте эти файлы в Git, выполните коммит изменений, а потом push. После перехода по ссылке у вас должно запуститься приложение:

Поздравляю! Теперь вы можете продолжить разработку приложения, а когда это необходимо — публиковать его на Heroku.

Если что-то пошло не так и приложение не запустилось

Предположим, что при запуске приложения по ссылке вы видите такую картинку:

Heroku нам подсказывает, что можно посмотреть логи запуска. Выполните команду heroku logs --tail в новом окне терминала git bash и посмотрите вывод — в нём будут следующие строки:

2020-04-12T20:39:13.390962+00:00 heroku[web.1]: State changed from crashed to starting
2020-04-12T20:39:12.841154+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
2020-04-12T20:39:12.849514+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -XX:+UseContainerSupport -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8
2020-04-12T20:39:13.202216+00:00 app[web.1]: no main manifest attribute, in target/blog-engine-1.0.jar
2020-04-12T20:39:19.058629+00:00 heroku[web.1]: State changed from starting to crashed

Если вы получили такой ответ, очевидно, была попытка запуска приложения — и можно посмотреть, с какими именно параметрами. Кстати, вполне понятно, почему не запустилась: Heroku не может определить, какой класс Main запускать. Логично, ведь контейнер читает информацию из MANIFEST.INF.

Такую проверку вы можете создать сами. Для этого скомпилируйте проект, выполнив команду maven install, например, из IDEA.

Теперь можно попробовать запустить jar из корня проекта:

Этот пример показывает, что проблему можно решить локально: проверить на своём компьютере в IDEA, а уже потом отправить приложение на Нeroku.

Для этого нужно сделать следующее:

  • Проверьте, что все необходимые файлы конфигурации на месте и вы добавили все строки на свои места.
  • Попробуйте выполнить Reimport pom.xml — файла конфигурации Maven.
  • Проверьте, что все файлы добавлены в Git и все их изменения закоммичены.

После этого добейтесь локального запуска вашего JAR-файла — главное, чтобы запустился Spring, — а затем отправляйте приложение в облако через push.

12. Подытожим

Ну вот, теперь вы можете не только публиковать Spring-Boot-приложения на Heroku, но и отлаживать, читать логи запуска и решать возникающие проблемы. Желаю быстрых деплоев и стабильной работы вашему коду.

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Java-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована