Pull to refresh

Мега-Учебник Flask, Часть XVIII: Развертывание на Heroku

Reading time12 min
Views39K

(издание 2018)


Miguel Grinberg




Туда Сюда


Это восемнадцатая часть серии Мега-учебников Flask, в которой я собираюсь развернуть микроблог на облачной платформе Heroku.


Под спойлером приведен список всех статей этой серии 2018 года.



Примечание 1: Если вы ищете старые версии данного курса, это здесь.


Примечание 2: Если вдруг Вы захотели бы выступить в поддержку моей(Мигеля) работы, или просто не имеете терпения дожидаться статьи неделю, я (Мигель Гринберг)предлагаю полную версию данного руководства(на английском языке) в виде электронной книги или видео. Для получения более подробной информации посетите learn.miguelgrinberg.com.


В предыдущей статье я показал вам «традиционный» способ размещения приложения Python, и представил вам два реальных примера развертывания на Linux-серверах. Если вы не на "ТЫ" системой Linux, то вероятно вам показалось, что объем затраченных усилий на такое развертывание был слегка больше ожидаемого, и, безусловно, должен быть более простой способ.


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


Многие облачные хостинг-провайдеры предлагают управляемую платформу, на которой можно запускать веб-приложения. Все, что вам нужно предоставить, чтобы ваше приложение было развернуто на этих платформах, — это фактическое приложение, потому что аппаратное обеспечение, операционная система, интерпретаторы языка сценариев, база данных и т.д. управляются службой. Этот тип сервиса называется Platform as a Service или PaaS.


Звучит слишком хорошо, чтобы быть правдой, не так ли?


Я буду развертывать Microblog на Heroku, популярном облачном сервисе, который также очень удобен для приложений Python. Я выбрал Heroku не только потому, что он популярен, но и потому, что у него есть бесплатный уровень обслуживания, который позволит вам следовать за мной и выполнять полное развертывание, не тратя никаких денег.


Ссылки GitHub для этой главы: Browse, Zip, Diff.


Хостинг на Heroku


Heroku, одна из первых облачных платформ, которая появилась в июне 2007 года и изначально поддерживала только язык программирования Ruby, но на данный момент список поддерживаемых языков также включает в себя Java, Node.js, Scala, Clojure, Go, PHP и конечно Python.


Развертывание веб-приложения в Heroku выполняется с помощью средства управления версиями git, поэтому приложение должно находиться в репозитории git. Heroku ищет файл под названием Procfile в корневом каталоге приложения для получения инструкций о том, как запустить приложение. Для проектов Python, Heroku потребуется файл requirements.txtфайл со списком всех зависимостей модулей, которые необходимо установить. После того, как приложение будет загружено на серверы Heroku через git, вы, по сути всё сделали, и нужно просто подождать несколько секунд, пока приложение появится в сети. Это действительно так просто.


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


Готовы попробовать Heroku? Давайте начнем!


Создание учетной записи Heroku


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


Установка Heroku CLI


Heroku предоставляет командную строку для взаимодействия с службой под названием Heroku CLI, доступной для Windows, Mac OS X и Linux. Документация содержит инструкции по установке для всех поддерживаемых платформ. Установите его в своей системе, если вы планируете развертывать приложение для тестирования службы.


Первое, что вы должны сделать после установки CLI, это войти в ваш Heroku аккаунт:


$ heroku login

Heroku CLI попросит вас ввести свой адрес электронной почты и пароль учетной записи. Ваш аутентифицированный статус будет сохранен в последующих командах.


Настройка Git


Инструмент git является основой для развертывания приложений в Heroku, поэтому вы должны установить его в своей системе, если у вас его еще нет. Если у вас нет пакета, доступного для вашей операционной системы, вы можете посетить сайт git для загрузки установщика.


Есть множество причин использовать git для ваших проектов. Если вы планируете развертывание в Heroku, то у вас появилась еще одна, потому что для развертывания в Heroku ваше приложение должно быть в репозитории git. Если вы собираетесь выполнить тестовое развертывание для Микроблога, вы можете клонировать приложение из GitHub:


$ git clone https://github.com/miguelgrinberg/microblog
$ cd microblog
$ git checkout v0.18

Команда git checkout выбирает конкретную точку фиксации приложения в его истории, соответствующей этой главе.


Если вы предпочитаете работать с собственным кодом, а не с моим, вы можете преобразовать свой собственный проект в репозиторий git, запустив git init . в каталоге верхнего уровня (обратите внимание на точку после init, которая является инструкцией для git, что вы хотите создать репозиторий в текущем каталоге).


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


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


$ heroku apps:create flask-microblog
Creating flask-microblog... done
http://flask-microblog.herokuapp.com/ | https://git.heroku.com/flask-microblog.git

Heroku требует, чтобы приложения имели уникальное имя. Имя flask-microblog, которое я использовал выше, не будет вам доступно, потому что я уже использую его, поэтому вам нужно будет выбрать другое для вашего развертывания.


На выходе этой команды мы получим URL, который Heroku назначил приложению, а также его репозиторий git. Ваш локальный репозиторий git уже будет иметь настройку связи с внешним(remote), называемым heroku. Вы можете убедиться, что он существует с помощью команды git remote:


$ git remote -v
heroku  https://git.heroku.com/flask-microblog.git (fetch)
heroku  https://git.heroku.com/flask-microblog.git (push)

В зависимости от того, как вы создали свой репозиторий git, вывод вышеуказанной команды также может включать в себя еще один удаленный источник с именем origin.


Эфемерная файловая система


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


Работа в этих условиях создает некоторые проблемы для моего приложения, которое использует несколько файлов:


  • Компонент SQLite database engine по умолчанию записывает данные в файл на диске
  • Журналы для приложения записываются в файловую систему
  • Скомпилированные хранилища языковых переводов также хранятся в локальных файлах

В следующих разделах будут рассмотрены эти три направления.


Работа с базой данных Heroku Postgres


Чтобы решить первую проблему, я перейду на другой механизм базы данных. В главе 17 вы видели, как я использую базу данных MySQL, чтобы повысить надежность развертывания Ubuntu. У Heroku есть собственное предложение базы данных, основанное на Postgres, поэтому я собираюсь переключиться на него, чтобы избежать проблемы хранения SQLite на основе файлов.


Базы данных для приложений Heroku снабжаются одним и тем же CLI Heroku. В этом случае я собираюсь создать базу данных на бесплатном(free) уровне:


$ heroku addons:add heroku-postgresql:hobby-dev
Creating heroku-postgresql:hobby-dev on flask-microblog... free
Database has been created and is available
 ! This database is empty. If upgrading, you can transfer
 ! data from another database with pg:copy
Created postgresql-parallel-56076 as DATABASE_URL
Use heroku addons:docs heroku-postgresql to view documentation

URL-адрес вновь созданной базы данных хранится в переменной среды DATABASE_URL, которая будет доступна при запуске приложения. Это очень удобно, так как приложение уже ищет URL базы данных в этой переменной.


Ведение журнала в stdout


Heroku ожидает, что приложения будут совершать ввод/вывод непосредственно в stdout. Все, что приложение печатает в стандартном выводе сохраняется и возвращается при использовании команды heroku logs. Поэтому я собираюсь добавить переменную конфигурации, которая указывает, нужно ли мне вести записи в stdout или в файл, как я это делал ранее. Вот изменение в конфигурации:


config.py: Опция ведения журнала в stdout.

class Config(object):
    # ...
    LOG_TO_STDOUT = os.environ.get('LOG_TO_STDOUT')

Затем в функции фабрики приложений я могу проверить эту конфигурацию, чтобы понять, как настроить средство ведения журнала приложения:


app/__init__.py: Журнал в stdout или в файл.

def create_app(config_class=Config):
    # ...
    if not app.debug and not app.testing:
        # ...

        if app.config['LOG_TO_STDOUT']:
            stream_handler = logging.StreamHandler()
            stream_handler.setLevel(logging.INFO)
            app.logger.addHandler(stream_handler)
        else:
            if not os.path.exists('logs'):
                os.mkdir('logs')
            file_handler = RotatingFileHandler('logs/microblog.log',
                                               maxBytes=10240, backupCount=10)
            file_handler.setFormatter(logging.Formatter(
                '%(asctime)s %(levelname)s: %(message)s '
                '[in %(pathname)s:%(lineno)d]'))
            file_handler.setLevel(logging.INFO)
            app.logger.addHandler(file_handler)

        app.logger.setLevel(logging.INFO)
        app.logger.info('Microblog startup')

    return app

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


$ heroku config:set LOG_TO_STDOUT=1
Setting LOG_TO_STDOUT and restarting flask-microblog... done, v4
LOG_TO_STDOUT: 1

Скомпилированные переводы


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


Более элегантный вариант, на мой взгляд, заключается в том, чтобы включить команду flask translate compile в команду start up, предоставленную Heroku, так что каждый раз, когда сервер перезапустится эти файлы скомпилируются снова. Я собираюсь пойти этим путём, так как я знаю, что моя процедура запуска будет требовать более одной команды в любом случае, так как мне ещё нужно запустить миграцию базы данных. Поэтому сейчас я отложу эту проблему в сторону и вернусь к ней позже, когда напишу Procfile.


Хостинг Elasticsearch


Elasticsearch является одним из многих сервисов, которые могут быть добавлены к проекту Heroku, но в отличие от Postgres, это не услуга, предоставляемая Heroku, а третья сторона, которая сотрудничают с Heroku, чтобы обеспечить дополнения. На сегодняшний день(когда я пишу эти строки) есть три разных провайдеров комплексной службы elasticsearch.


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


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


$ heroku addons:create searchbox:starter

Эта команда развернет службу Elasticsearch и разместит URL-адрес подключения для службы в переменной среды SEARCHBOX_URL, связанной с приложением. Еще раз напомню, что эта команда не будет выполнена, если Вы не добавите свою кредитную карту в свой аккаунт Heroku.


Если вы вспомните из главы 16, мое приложение ищет URL-адрес подключения Elasticsearch в переменной ELASTICSEARCH_URL, поэтому мне нужно добавить эту переменную и установить ее в URL-адрес подключения, назначенный SearchBox:


$ heroku config:get SEARCHBOX_URL
<your-elasticsearch-url>
$ heroku config:set ELASTICSEARCH_URL=<your-elasticsearch-url>

Здесь я сначала попросил Heroku напечатать значение SEARCHBOX_URL, а затем я добавил новую переменную среды с именем ELASTICSEARCH_URL, установленным в то же значение.


Обновление Requirements


Heroku ожидает, что зависимости будут в файле requirements.txt, точно так же, как я определил в главе 15. Но для запуска приложения на Heroku мне нужно добавить две новые зависимости к этому файлу.


Heroku не предоставляет собственный веб-сервер. Вместо этого он ожидает, что приложение запустит свой собственный веб-сервер по номеру порта, указанному в переменной среды $PORT. Поскольку Веб-сервер разработки flask недостаточно надежен для использования в работе, я собираюсь снова использовать gunicorn, сервер, рекомендованный Heroku для приложений Python.


Приложение также будет подключаться к базе данных Postgres, и для этого SQLAlchemy требует установки пакета psycopg2.


И gunicorn и psycopg2 нужно быть добавленным в файл requirements.txt.


Профайл


Heroku должен знать, как выполнить приложение, и для этого он использует файл с именем Procfile в корневом каталоге приложения. Формат этого файла прост, каждая строка содержит имя процесса, двоеточие, а затем команду, которая запускает процесс. Наиболее распространенным типом приложения, который работает на Heroku, является веб-приложение, и для этого типа приложений имя процесса должно быть web. Ниже вы можете увидеть Procfile для Microblog:


Procfile: Heroku Procfile.

web: flask db upgrade; flask translate compile; gunicorn microblog:app

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


Поскольку первые две подкоманды основаны на команде flask, мне нужно добавить переменную среды FLASK_APP:


$ heroku config:set FLASK_APP=microblog.py
Setting FLASK_APP and restarting flask-microblog... done, v4
FLASK_APP: microblog.py

Команда gunicorn проще, чем то, что я использовал для развертывания Ubuntu, потому что этот сервер имеет очень хорошую интеграцию со средой Heroku. Например, переменная среды $PORT учитывается по умолчанию, и вместо того, чтобы использовать параметр -w для задания числа процессов, heroku рекомендует добавить переменную WEB_CONCURRENCY, которую gunicorn использует, когда -w не предоставляется, что дает вам гибкость для управления числом процессов без необходимости изменять Procfile.


Развертывание приложения


Все подготовительные шаги завершены, поэтому пришло время запуска развертывания. Для загрузки приложения на серверы Heroku для развертывания используется команда git push. Это похоже на отправку изменений в локальном репозитории git на GitHub или другой удаленный сервер git.


И теперь я достиг самой интересной части, где я отправляю приложение на свой хостинг-аккаунт Heroku. Это на самом деле довольно просто, я просто должен использовать git, чтобы подтолкнуть приложение к главной ветви репозитория Heroku git. Существует несколько вариантов того, как это сделать, в зависимости от того, как вы создали свой репозиторий git. Если вы используете мой код v0.18, то вам нужно создать ветвь на основе этого тега, и отправить её к удаленной ветви master, следующим образом:


$ git checkout -b deploy
$ git push heroku deploy:master

Если вы всё же работаете с собственным репозиторием, то ваш код уже, скорее всего, находится в главной ветви, поэтому вам сначала нужно убедиться, что ваши изменения пофиксены:


$ git commit -a -m "heroku deployment changes"

После чего можно запустить развертывание следующим образом:


$ git push heroku master

Независимо от того, как вы отправляете ветку, вы должны увидеть следующий вывод из Heroku:


$ git push heroku deploy:master
Counting objects: 247, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (238/238), done.
Writing objects: 100% (247/247), 53.26 KiB | 3.80 MiB/s, done.
Total 247 (delta 136), reused 3 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing python-3.6.2
remote: -----> Installing pip
remote: -----> Installing requirements with pip
...
remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 57M
remote: -----> Launching...
remote:        Released v5
remote:        https://flask-microblog.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/flask-microblog.git
 * [new branch]      deploy -> master

Метка heroku, которую мы использовали в команде git push, — это удаленный репозиторий, который был автоматически добавлен HEROKU CLI при создании приложения. Аргумент deploy:master означает, что я перемещаю код из локального репозитория, на который ссылается ветвь deploy, в главную ветвь master репозитория Heroku. Когда вы работаете с вашими собственными проектами, вы, вероятно, будете проталкивать изменения с помощью команды git push heroku master, которая протолкнет(запушит) вашу локальную ветку master. Из-за того, как этот проект структурирован, я отправляю ветку, которая не является master, но ветка назначения на стороне Heroku всегда должна быть master, поскольку это единственная ветвь, которую Heroku принимает для развертывания.


И вот теперь приложение должно быть развернуто по URL-адресу, указанному в выходных данных команды, создавшей приложение. В моем случае URL был https://flask-microblog.herokuapp.com, так что это то, что мне нужно ввести, чтобы получить доступ к приложению.


Если вы хотите видеть записи журнала для работающего приложения, используйте команду heroku logs. Это может быть полезно, если по какой-либо причине приложение не запускается. Если были какие-либо ошибки, они будут в журналах.


Развертывание обновлений приложений


Чтобы развернуть новую версию приложения, вам просто нужно выполнить команду git push с новым кодом. Это повторит процесс развертывания, отключит старое развертывание и заменит его новым кодом. Команды в Procfile будут запускаться снова как часть нового развертывания, поэтому любые новые миграции или переводы базы данных будут обновляться во время процесса.


Туда Сюда

Tags:
Hubs:
+9
Comments2

Articles

Change theme settings