Skip to content

Latest commit

 

History

History
236 lines (144 loc) · 20 KB

File metadata and controls

236 lines (144 loc) · 20 KB

Heroku

PaaS

Мы с вами научились выкладывать наши сайты и ботов на Pythonanywhere, но это не единственный вариант. Существуют другие подобные сервисы - Heroku, Scalingo, Openshift.

Все они являются PaaS - Platform-as-a-Service, которые позволяют вам очень просто пользоваться облачным хостингом и быстро выкладывать свои приложения вместо того, чтобы самостоятельно настраивать сервер.

От Pythonanywhere они отличаются тем, что для них разработчиками не всегда предоставлен такой же удобный веб-интерфейс, в котором многое делается кнопочками в панели управления, и нужный функционал мы получем через командную строку Unix. Но ощее с Pythonanywhere у них то, что там есть возможность делать хотя бы что-то из того, что вам нужно, бесплатно.

Дело в том, что вслед за компанией Amazon многие другие IT-компании стали предоставлять пользователям (в числе которых и частные лица, и компании поменьше) облачные сервисы, то есть возможность не содержать на свои средства большой парк серверов (это часто неудобно, потому что бесперебойную работу серверов обеспечить не так просто), а покупать место на мощных серверах, которые содержит хозяин облака. Основные конкурирующие на этом поле сервисы -- это Amazon Web Services, Google Cloud и Microsoft Azure. Все они платные (Google предоставляет на своей платформе условно-бесплатный тестовый период в один месяц), но мощные и надёжные.

Почему еще и Heroku?

У бесплатных аккаунтов Heroku есть некоторое количество преимуществ перед аналогичными аккаунтами Pythonanywhere:

Pythonanywhere Heroku
только одно приложение несколько приложений
свой домен - платная функция позволяет использовать собственное доменое имя
ограниченный доступ к внешним ресурсам доступ к внешним ресурсам не ограничен

Подробнее про ограниченный доступ: на Pythonanywhere можно обращаться лишь к тем сайтам, которые входят в белый список разрешенных ресурсов. Т.е. например, наш сайт, который регулярно скачивает новости с hse.ru не будет работать на Pythonanywhere, потому что hse.ru не включен в белый список. На Heroku таких ограничений нет.

Подробнее про количество бесплатных приложений: на Heroku можно создавать несколько приложений бесплатно лишь до тех пор, пока у вас есть свободные Dyno (про это будет ниже).

Подготовка к выкладыванию

  1. Чтобы наш фласк-сайт или фласк-бот заработал на Heroku, нужно убедиться, что в конце основной программы написан вот такой код:
if __name__ == '__main__':
    import os
    app.debug = True
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)
  1. В директории с вашим фласк-приложением обязательно должны быть следующие три файла:

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

        Flask==0.12.1
        pymorphy2==0.8
        pymystem3==0.1.5
        requests==2.13.0
      

    Обратите внимание, что в этот список НЕ НУЖНО писать setuptools и pip!

    Когда вы будете выкладывать приложение, Heroku прочитает файл requirements.txt и установит все перечисленные модули командой pip install -r requirements.txt.

    • runtime.txt - в этом файле нужно написать одну строчку:

        python-3.6.1
      

    Если в директории нет runtime.txt, то Heroku будет по умолчанию думать, что ваше приложение написано на Python 2.7.

    • Procfile - обратите внимание, что у файла нет расширения, иначе heroku не сможет прочитать его содержимое. В этом файле нужно написать одну строчку:

         web: python flask_app.py
      

    Вместо flask_app.py нужно написать название вашего файла с фласк-приложением. Procfile - это специальный файл, в котором нужно объяснить Heroku, как именно нужно запускать ваше приложение. web значит, что мы написали приложение, которое отвечает на http-запросы, python flask_app.py обозначает команду, с помощью которой приложение запускается.

  2. Для выкладывания приложений на Heroku используется git. Поэтому если в вашей директории с проектом еще нет git-репозитория, его нужно создать. Открываем терминал (Mac, Linux) или командную строку (Windows) и пишем:

    • cd путь-к-директории - переходим в директорию с нашим фласк-проектом,
    • git init - создаем в текущей директории репозиторий,
    • git add * - говорим гиту следить за всеми файлами в репозитории,
    • git commit -m 'Initial commit' - делаем первый коммит.

Как выложить сайт на Heroku?

  1. Зарегистрироваться на сайте Heroku, ваш email будет логином. Когда вы зарегистрировались, вы попадаете в Dashboard. Сейчас у вас там ничего нет - вам предлагают создать приложение (an app) или пройти туториал по работе с Heroku и выбранного вами языка программирования. Туториал по питону там ориентирован на джанго, мы работаем с фласком, так что наши действия будут слегка отличаться.

  2. Скачать установщик для вашей ОС и установить Heroku CLI - Command Line Interface - https://devcenter.heroku.com/articles/heroku-cli

  3. Открыть терминал (Mac, Linux) или командную строку (Windows) и выполнить команды:

    • cd путь-к-директории - переходим в директорию с нашим фласк-проектом,
    • heroku login - логинимся в наш аккаунт Heroku,
    • ввести свой емейл и пароль, с которыми мы зарегистрировались,
    • heroku create - создаем приложение, которое поможет Heroku получить наш код и запустить его. В этот момент Heroku делает сразу несколько вещей.

    Во-первых, он генерирует случайное название для нашего приложения, но можно передать ваше собственное название, например, heroku create my-app-04062017. Ваш сайт будет доступен по адресу имя-приложения.herokuapp.com.

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

    • git push heroku master - эта команда отправляет наш код на облачный хостринг, и Heroku устанавливает нужные модули.

    • heroku ps:scale web=1 - эта команда говорит запустить наш фласк-сайт на одном dyno.

      A dyno is a lightweight Linux container that runs a single user-specified command.

      То есть ваш сайт или бот будет работать на маленьком виртуальном Линукс-"сервере". Бесплатно вам доступно 550 или 1000 таких dyno.

    • heroku open - эта команда открывает ваш сайт в браузере. Ура! Все готово!

    • Если по какой-то причине сайт не заработал, то нужно посмотреть логи:

      • heroku logs - эта команда распечатает 100 последних строчек логов, т.е. если произошла какая-то ошибка, то информацию об этой ошибке вы увидите в конце логов.
      • или heroku logs --tail - эта команда показывает логи в реальном времени, т.е. если ваша программа что-то печатает в консоль с помощью print(...) или питон печатает сообщение об ошибке, то вы будете в реальном времени видеть, что именно происходит.
      • подробнее - https://devcenter.heroku.com/articles/logging

Когда вы меняете что-то в вашей программе\директории, то изменения нужно отправить на Heroku:

	git add *
	git commit -m "Demo"
	git push heroku master
	heroku ps:scale web=1

Секретные ключи

Поскольку мы отправляем все файлы на Heroku через git, возникает небольшая проблема:

Что если у нас есть секретные файлы (например, API-токены или пароли), которые включены в .gitignore? Получается, мы никак не сможем отправить эти секретные файлы на облачный хостинг через git.

Переменные среды

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

Раньше мы с вами писали секретные ключи в игнорируемый файл (например, TOKEN = "......" внутри conf.py) и импортировали секретные переменные с помощью from conf import *.

Вместо этого, можно установить переменную среды прямо в терминале\командной строке:

  • Mac, Linux - export SOME_SECRET_KEY=1c3-cr3am-15-yummy
  • Windows - set SOME_SECRET_KEY 1c3-cr3am-15-yummy (если у вас Windows 10, то setx)
  • Heroku - heroku config:set SOME_SECRET_KEY=1c3-cr3am-15-yummy

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

>>> import os
>>> os.environ["SOME_SECRET_KEY"]
"1c3-cr3am-15-yummy"

То есть строчку from conf import * вам придется заменить на строчки вида:

import os
SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]

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

import flask
import telebot
import os

TOKEN = os.environ["TOKEN"]


bot = telebot.TeleBot(TOKEN, threaded=False)


bot.remove_webhook()
bot.set_webhook(url="https://<your app_name>.herokuapp.com/bot")

app = flask.Flask(__name__)

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.send_message(message.chat.id, "Здравствуйте! Это бот, который считает длину вашего сообщения.")


@bot.message_handler(func=lambda m: True)  # этот обработчик реагирует все прочие сообщения
def send_len(message):
    bot.send_message(message.chat.id, 'В вашем сообщении {} символов.'.format(len(message.text)))

@app.route("/", methods=['GET', 'HEAD'])
def index():
    return 'ok'

# страница для нашего бота
@app.route("/bot", methods=['POST'])
def webhook():
    if flask.request.headers.get('content-type') == 'application/json':
        json_string = flask.request.get_data().decode('utf-8')
        update = telebot.types.Update.de_json(json_string)
        bot.process_new_updates([update])
        return ''
    else:
        flask.abort(403)
    
if __name__ == '__main__':
    import os
    app.debug = True
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)

Как запустить что-то по расписанию?

Если вы делаете какой-то веб-сервис, который должен обновлять какие-то данные через определённые промежутки времени (например, каждый день в 12:00 или каждый четверг в 17:25), то вы можете настроить стандартную Unix-утилиту cron, которая умеет запускать на сервере какой-то нужный пользователю процесс в тот момент, когда это ему необходимо.

Утилита cron обычно уже входит в стандартную сборку дистрибутива и устанавливать её не нужно. Она имеет текстовый интерфейс настройки, то есть расписание придётся писать через консоль, в одном из консольных текстовых редакторов. Наиболее популярный из них -- Vim. Он не очень прост в обращении, потому что неинтуитивен. Перед тем, как его запускать, узнайте, как его закрыть (почти как в сказке, нужно помнить про "горшочек, не вари", прежде чем сказать "горшочек, вари"). Недавно крупный сайт подсказок и ответов на вопросы о программировании Stackoverflow опубликовал новость, из которой следует, что вопрос "как выйти из Vim" является чуть ли не самым популярным при поиске вопросом.

Есть и другой консольный редактор, nano, он проще и все команды, которые вы должны выполнить для тех или иных действий, постоянно показываются внизу экрана ("крышечка" означает "Ctrl"):

nano

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

Создать или отредактировать расписание можно вызовом команды crontab -e. В открывшемся окне нужно будет описать в формате cron, что вы хотите, чтобы было сделано, и когда это должно быть сделано. Формат cron подразумевает, что вы напишете минута час день_месяца месяц день_недели команда, а потом -- то, что должно будет запуститься, в том виде, в котором бы вы сами это запускали вручную в командной строке.

Примеры расписания в cron:

# нечто будет выполняться каждую минуту:
* * * * * python3 /home/user/script.py

# только по выходным:
* * * * 6,7 python3 /home/user/weekend.py

# дважды в день:
20 11,16 * * * python3 /home/user/twice.py

# один раз в году, в полночь 1-го января:
0 0 1 1 * python3 /home/user/HappyNewYear.py

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

Полезная ссылка

Тут можно найти ещё одно руководство по запуску бота на хероку.