Разворачиваем приложение на Heroku

Heroku - облачная платформа для хостинга приложений

Heroku - удобная платформа для разворачивания контейнерных приложений. Что такое облачная платформа и что такое контейнеры - далее.

Что такое облачная платформа. Как это работает?

Что такое облако? Облако - много-много железных серверов, находящихся где-то не важно где, и ухаживают за ними какие-то другие люди.

Но нам то важно то, как мы можем этим пользоваться, а пользоваться можно вот как:

  1. Хостер виртуальную машину и даёт нам доступ к ней. Мы можем туда установить операционную систему и делать в этой операционной системе всё что захотим.

    То есть нам дают собаку, но кормить её не надо, её кормят другие.

Пример такого хостинга: RU VDS. Оплата по количеству часов

  1. Хостер сам устанавливает операционную систему, сам её настраивает, а мы ему отдаём только наше приложение и инструкции для запуска этого приложения. Для этого придуманы контейнеры - способ организации самого приложения и инструкций к его запуску.

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

Пример: Heroku. Оплата по часам, есть бесплатный тариф

  1. Хостер уже имеет у себя какие-то маленькие приложения и компоненты. Всё, что остаётся сделать нам - правильно из всего этого конструктора собрать своё приложение.

    Мы составляем список игр, в которые мы хотим поиграть с собакой и нам под каждую игру дают отдельную собаку.

Пример: Firebase. Оплата по количеству запросов, есть бесплатный тариф

Почему Heroku?

  1. Бесплатно: 570 часов работы каждый месяц (19 часов/день), 10k строчек в БД (PostgreSQL) и кое-что ещё - достаточно неплохо для небольшого проекта
  2. Нам не надо думать об операционной системе, о всяких страшных вещах настройках
  3. Очень простая настройка контейнеров. Мы можем написать приложение на почти любом языке, и одной строчкой в Procfile рассказать, как конкретно ваше приложение нужно запустить
  4. Можно спокойно запустить приложение на своём компьютере или другом сервере, ведь всё, что относится к Heroku - Procfile, всё остальное - ваше приложение
  5. Можно настроить так, что приложение само будет обновляться, нам останется только код писать
  6. При регистрации не нужно никаких кредитных карточек

Для какого рода приложений хорошо:

  • Боты
  • Чаты
  • Что-то, что будет работать не часто и по запросу

Для чего можно использовать, но не рекомендуется:

  • Блоги или статические сайты - тут можно использовать какой-нибудь uCoz или Tilda
  • Бекэнд для мобильных приложений - тут лучше посмотреть в сторону Firebase, там для мобилок много интересного
  • Сервер для чего-то, что должно работать 24/7, например стриминговый сервис для хомячков - тот же RU VDS. Специально для python приложений есть такая вещь как PythonAnywhere

Некоторые тонкости работы

И так, как же работает Heroku.

Ваше приложение не работает всё время: оно включается тогда, когда к нему пришёл какой-то запрос и работает после этого ещё 30 минут, вдруг ещё кто-то придёт. Время считается именно за включенное приложение.

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

Минусы - приложение запускается на самом деле не очень быстро, так что может возникунть проблема того, что пользователь будет минутку другую ждать пока ему придёт ответ от нашего сервера, но зато остальное время будет достаточно шустро работать. Для разного рода ботов проблема не большая - сервера телеги или вк всегда пришлют ещё один запросик, чтобы уж точно дошёл, но отвечать бот на первое сообщение будет долго. А вот для системы слежения за хомячками - уже больше проблем.

Так же платформа имеет buildpack для разных языков (Node.js, Python, Ruby, PHP, Java, Clojure, Scala, Go). Это всё из бесплатных buildpack’ов, так же вы можете “докупить” под что-то относительно экзотическое, например MySQL базу данных или RabbitMQ очередь для своего проекта. Ну или, например, C++ среду для какой-то своей очень очень ресурсоёмкой задачи.

Buildpack - полуфабрикат для какого-то контейнера. В хероку в этих buildpack’ах спрятана разная магия по установке интерпретаторов языков, установке зависимостей и разного интересного. Всё, что нам нужно знать - что они бесплатные и делают грязную работу за нас, нам нужно только подкинуть туда свои исходники и немного настроить с помощью файла Procfile.

Но часто вполне хватает Python + PostgreSQL.

Перейдём к развёртыванию!

Для примера возьмём вот такое сферическое приложение в вакууме:

  • Наше приложение наприсано на Python
  • Мы используем Flask
  • Нам нужна БД
  • Приложение является ботом
  • Все исходники приложения хранятся на GitHub

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

Для начала потренеруемся на кошечках

Давайте сначала определимся, где мы находимся. Все последующие инструкции работают в 2 разных средах: сайт Heroku, консоль. Консоль может быть либо стандартная в Linux, либо PowerShell, если Вы работаете из под Windows.

  1. Запустите свою консоль
  2. Введите pip3 --version

Если система сказала что-то плохое, а не pip X.X.X from XXX, то есть несколько вариантов развития событий. Давайте пройдёмся по каждому:

  1. У вас в системе есть просто pip => команда должна быть pip --version
  2. У вас в системе только python установлен “глобально” => команда должна быть такая: python -m pip --version
  3. У вас в системе в принципе python установлен неправильно => обратитесь к хелпдеску

Регистрация

Для того, чтобы воспользоваться чем-то, нужно зарегистрироваться.

  1. Заходим на страницу регистрации
  2. Первые 3 поля - обязательные для честного заполнения. Остальное - для статистики внутри хероку. Но компанией вы можете назвать свою команду, себя представить студентом, а любимый язык выбрать по вкусу.
  3. Не забудьте прочитать Правила!

Создание приложения

После регистрации и подтверждения email адреса нас должно впустить в Dashboard. Это панель управления. Тут будут находится все наши приложения.

  1. Теперь мы можем нажать на кнопку “New” и выбрать “Create New App”
  2. Каким-то образом называем наше приложение. Это нужно потому, что потом наше приложение будет доступно по адресу https://<appname>.herokuapp.com, ну и приложение должно иметь какое-то уникальное имя.
  3. Страна развёртывания - где будет ваше приложение храниться, в каком датацентре. На самом деле интернет не такой уж и большой, но от нас ближе Европа, так что давайте выберем её.

Нас сразу перекинуло на вкладку “Deploy”. Так что продолжим

Развёртывание

Способов передачи приложения серверам хероку очень много - и ручные, и специальные git репозитории, и Docker образы. Нам всё это не интересно, потому что это всё сложные технологии для бородатых дядек, которые едят на завтрак материнские платы, запивая смуззи из пива.

Мы люди простые, нам хочется чтобы всё делалось автоматом, поэтому мы привяжем GitHub-репозиторий!

  1. Выбираем вкладку “GitHub”
  2. Проходим процесс “привязки” GitHub-аккаунта
  3. Находим свой репозиторий с помощью специального поля поиска
  4. Нажимаем кнопку “Connect”

Теперь давайте включим автоматическое развёртывание. Для этого в секции “Automatic deploys” нажимаем кнопку “Enable Automatic Deploys”.

Всё! Теперь когда мы даем какой-то коммит в master ветку нашего репозитория хероку автоматически будет забирать все исходники из репозитория и разворачивать приложение.

Инструкции к разворачиванию

- А какой язык ты используешь, расскажи?

На самом деле сейчас Heroku не сможет ничего развернуть. Потому что он даже не знает, как к нашему приложению подойти: может это Ruby приложение, может вообще Java!

Как я уже говорил, у Heroku есть разные buildpack’и для разных языков и платформ. Чтобы узнать, какой из этих buildpack’ов использовать, Heroku полагается на файлы-идикаторы.

Для Ruby таким файлом будет Gemfile, для Node.js - package.json. А в нашем случае (Python) файлом-индикатором является requirements.txt

Давайте сделаем файл-индикатор. В файле requirements.txt по договорённости всех разработчиков должны храниться названия и версии всех пакетов, которые необходимы для работы приложения. Создать этот файл очень просто:

pip3 freeze > requirements.txt

Теперь если мы захотим запустить наш сервер на другом компьютере, мы выполним следующую команду и pip сам установит все необходимое.

pip3 install -r requirements.txt

И всё, у него теперь всё на месте и всё должно работать.

Пример файла requirements.txt можете посмотреть здесь.

- А как мне теперь всё это запустить?

Теперь хероку знает как к этому делу подступиться, но он не знает, как запустить наше приложение. Да и вообще, об этом пока знаем только мы.

Для начала нам нужно установить сервер, который будет запускать наше Flask приложение. Для этого мы установим специальный сервер gunicorn:

pip3 install gunicorn  # Устанавливаем локально
pip3 freeze > requirements.txt  # обязательно сохраняем, чтобы Heroku тоже установил этот пакет

Теперь осталось рассказать, как конкретно запускать наш сервер.

  1. Создадим файл Procfile с вот таким содержимым:
    web: gunicorn app:flask_app --log-file=- --log-level=debug
    
  2. Закомитим и запушим этот файл в GitHub

А теперь немного о том, что содержится в нашем Procfile:

  • web: - мы говорим, что эта команда должна запускаться при запросе на сайт https://<appname>.herokuapp.com
  • gunicorn - запускаем uWSGI сервер
  • app:flask_app - в python-модуле app в переменной flask_app хранится наше приложение
  • --log-level=debug --log-file=- - настройки логирования. Чтобы в случае падения хоть где-то было написано почему упало.

А как же БД?

Теперь давайте к нашему приложению подключим базу данных.

  1. Зайдём во вкладку “Resources”
  2. Введём там в поле поиска “heroku”
  3. Выбираем “Heroku Postgres”
  4. Подтверждаем подключение модуля к нашему приложению

Всё, круть! Нам доступна БД на 10k строк!

Но нам нужно, чтобы наше приложение подключилось к ней. Если мы перейдём во вкладку “Settings” и нажмём на кнопочку “Reveal Config Vars”, то увидим там строчку

key value
DATABASE_URL postgres://asdf:asdf.asdf@asdf.amazonaws.com/adsf

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

from os import getenv

db_url = getenv('DATABASE_URL')

Всё! Теперь мы умеем забирать настройки для приложения из переменных окружения. Вот как это делается у нас.

Теперь мы каким-то магическим образом по этому адресу подключаемся к БД. Например вот так.

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

Что же теперь?

А теперь вот вам несколько советов: 1.Все настройки (токены, пароли администраторов, любые данные для входа куда-нибудь) храните в переменных окуржения, а не в коде.

  1. Поиграйтесь немного с тем, что найдёте в интерфейсе Heroku. Например, вы можете полностью удалить все данные в БД, посмотреть логи своего приложения, использовать вместо appname.herokuapp.com свой собственный домен, вручную достать исходники из GitHub или принудительно перезапустить приложение.
  2. Не нажимайте на что-то, где не написано “free” или “0 $/month”. Конечно ничего сильно страшного не случится, ведь они сначала потребуют деньги, но отключать потом все эти платные функции - дело не очень приятное.

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

Ещё немного о возможностях платформы

Можно выполнять какие-то команды по расписанию. Вещь работает достаточно стабильно, хотя сами разработчики предупреждают, что иногда может давать осечки… Работает она так же как и простое приложение - как только запустилось, начались вычитываться месячные часы работы, как только закончило что-то выполнять - всё, списываться ничего не будет.

Ещё можно запускать “worker” процессы - которые будут работать постоянно. Но эти процессы будут так же есть часы в месяц, которые можно было использовать для работы основного приложения. Поэтому эта фича просто достойна упоминаний.