Как стать автором
Обновить
260.32
KTS
Создаем цифровые продукты для бизнеса

Первые шаги в aiohttp, часть 3: публикуем приложение в Интернете

Время на прочтение8 мин
Количество просмотров7.3K

Привет!

Сегодня разберем заключительную часть цикла «Первые шаги в aiohttp». В первой статье мы создали и настроили проект, а во второй подключили базу данных.

В этой части мы рассмотрим размещение нашего веб-сервиса в Интернете, используя платформу Heroku.

Что будет в статье:

  1. Подготовка

  2. Создаем необходимые файлы

  3. Пакуем приложение в Docker-контейнер

  4. Публикуем приложение через Heroku

  5. Исправляем ошибки

  6. Вместо заключения

  7. Как разобраться в асинхронном программировании на Python

Эта статья дополняет код второй части:
Код части 2

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

1 — Подготовка

Прежде всего необходимо зарегистрироваться на Heroku. Сделать это можно по этой ссылке.

Чтобы работать с Heroku из терминала, установите интерфейс командной строки Heroku CLI. Через него вы сможете работать с приложением на платформе Heroku. Инструкции по установке можно посмотреть здесь.

Обратите внимание: Heroku CLI требует установленный Git. Как его установить, читайте здесь.

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

2 — Создаем необходимые файлы

Прежде всего необходимо создать еще один конфигурационный файл, который будет использовать Heroku. В папке config/ создадим файл heroku_config.yaml и запишем в него следующее:

common:  
  port: $PORT 
postgres:   
  database_url: $DATABASE_URL   
  require_ssl: true

Знак доллара значит, что значение — переменная окружения, которая будет заменена в процессе публикации приложения.

Рассмотрим конфигурацию детальнее:

  • port: $PORT — Heroku каждый раз будет ждать, что ваше приложение запущено на новом порту, который выделила платформа. Поэтому конкретное значение записать нельзя.

  • database_url: $DATABASE_URL — url для подключения к Postgresql-базе данных. Мы воспользуемся бесплатным дополнением (addon) и создадим базу на платформе Heroku. В настройках Heroku мы можем узнать текущий адрес базы, который нам выделили, но он может динамически меняться, поэтому это значение тоже зависит от окружения.

  • require_ssl: true — база данных не находится в локальном месте, поэтому общение с ней происходит по Интернету. Чтобы данные не перехватили, нам нужно их шифровать по протоколу SSL. Heroku, кстати, вообще не позволяет устанавливать незащищенные соединения.

Чтобы Heroku смог применить миграции нашего приложения к базе в момент запуска, надо добавить в корень проекта файл run.sh и написать в нем:

# подставляем переменные из окружения в подготовленный конфиг
cat config/heroku_config.yaml | envsubst > config/config.yaml 
# необходимо для того, чтобы alembic смог найти наше приложение
export PYTHONPATH=. 
# обновляем версию базы до последней
alembic upgrade head 
# запускаем сервер
python main.py

3 — Пакуем приложение в Docker-контейнер

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

В корне приложения создадим файл Dockerfile:

# Docker-команда FROM указывает базовый образ контейнера
# Наш базовый образ - это Linux с предустановленным python-3.7
FROM python:3.7
# gettext-base нужен для того, чтобы установить envsubst
RUN apt update && apt -y install gettext-base
# Скопируем файл с зависимостями в контейнер
COPY requirements.txt .
# Установим зависимости внутри контейнера
RUN pip install -r requirements.txt
# Скопируем остальные файлы в контейнер
COPY . .
# разрешаем наш скрипт на исполнение операционной системой
RUN chmod +x run.sh
# запускаем скрипт
CMD ["./run.sh"]

Рассмотрим каждую команду:

  • FROM python:3.7 — берем образ ОС с предустановленным python версии 3.7.

  • RUN apt update && apt -y install gettext-base — устанавливаем необходимые пакеты

  • COPY requirements.txt . — копируем локальный файл в виртуальный контейнер

  • RUN pip install -r requirements.txt — устанавливаем необходимые python-зависимости

  • COPY . . — копируем остальные файлы нашего проекта в контейнер. Docker создает слой кэша на каждую команду, кроме команд запуска. Поэтому удобнее, если на первых строчках файла стоят команды, которые работают с редко изменяемыми данными — например с установкой модулей. А после них уже можно писать команды с часто изменяемыми — например? с копированием кода сервиса.
    Пример: если мы не будем менять requirements.txt, то после первой сборки Docker будет заново использовать слои, созданные до команды RUN pip install -r requirements.txt, что заметно ускорит сборку.

  • RUN cat config/heroku_config.yaml | envsubst > config/config.yaml— заменяем наш конфигурационный файл, подставляя на место значений со знаком $ одноименные переменные из окружения, используя pipe (знаки | и >).
    Пример: у нас в файле записана строка port: $PORT. Обрабатывая ее, envsubst постарается найти в окружении переменную с именем $PORT и подставить ее значение вместо текста “$PORT” в файле. Heroku сам добавит в наш контейнер все необходимые для работы переменные, например, $PORT и $DATABASE_URL, а envsubst подставит их на нужные места в файле конфигурации.

  • CMD ["./run.sh"] — запускаем наш скрипт, в котором выполняются миграции и запускается приложение. Это команда будет выполнена, когда мы или Heroku будем запускать контейнер с помощью команды docker run.

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

В проекте может быть несколько приложений одновременно, каждое из которых будет упаковано в отдельный Docker-контейнер. Например, API-сервис и микросервис для загрузки файлов. Чтобы Heroku мог понять, какое приложение нужно собирать и публиковать, добавьте в корень файл docker-compose.yaml со следующим содержимым:

version: '3' 
services:  
  web:     
    build: .

Docker-compose — инструмент для одновременного запуска и управления несколькими Docker-контейнерами, объединенными между собой. Например, с помощью docker-compose можно объединить контейнер нашего сервиса с контейнером базы данных, указав общую для них сеть, в которой они смогут «общаться», а также привязать volume — постоянное хранилище данных, которое будет автоматически создано или подключено. Мы создавали Volume во второй части. Также с помощью docker-compose можно указать зависимость контейнеров друг от друга. Это позволит избежать ситуаций, когда приложение запущено раньше базы данных, из-за чего происходит критическая ошибка при подключении. Это лишь часть способов применения docker-compose. Подробнее — в официальном руководстве.

Если в проекте несколько приложений и несколько Dockerfile, их необходимо публиковать по очереди. Поэтому каждый service в docker-compose.yaml должен иметь уникальное имя. В нашем случае приложение только одно, и в файле мы назвали его web.

4 — Публикуем приложение с помощью Heroku

Шаг 1: Создаем приложение

Для этого в терминале выполним команду:

heroku create forum

Если вы еще ни разу не использовали Heroku, в консоли должна появится такая надпись, :

Нажмите любую кнопку (кроме q) и откроется браузер со страницей входа в Heroku. После входа на сайте вы можете закрыть браузер и продолжить работу в консоли. Также можно явно авторизоваться, вызвав команду heroku login.

При выполнении команды create Heroku создает новый git-репозиторий для проекта или привязывает новый удаленный репозиторий к существующему локально.

forum — название приложения, которое одновременно будет префиксом в url: после публикации приложение будет доступно по url forum.heroku.com. Если не указать имя приложения при выполнении команды create, Heroku сгенерирует случайное название.

Если указанное вами имя уже используется, то Heroku напишет об этом.

Шаг 2: Выделяем бесплатную площадку для работы с базой данных

Нужно «попросить» Heroku о выделении базы командой:

heroku addons:create heroku-postgresql:hobby-dev

Рассмотрим команду подробнее:

addons:create — добавляем к нашему Heroku-приложению новое дополнение, которое называется heroku-postgresql, используя беплатный тарифный план 
hobby-dev.

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

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

При клике на Heroku Postgres вы увидите детальную информацию о дополнении. На вкладке settings можно посмотреть реальные данные для подключения к базе:

Шаг 3: Авторизуемся в хранилище образов

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

heroku container:login

В случае успеха вы должны увидеть "Login Succeeded".

Шаг 4: Собираем и загружаем образ приложения в хранилище

Необходимо собрать образ и отправить образ в хранилище Heroku, которое называется Registry. Сборка и отправка образа в Registry обычно выполняется командой push, а получение командой pull. Соберем и отправим образ (убедитесь, что Docker запущен перед выполнением этой команды):

heroku container:push web

Если взглянуть на логи после выполнения этой команды, мы увидим два этапа:

  • Сборка образа

  • Отправка образа

Действительно, сначала Heroku запустил сборку, выполнив все команды в Dockerfile, кроме последней — команды запуска приложения. Потом образ получил уникальный идентификатор, тесно связанный с его содержимым. Это сделано, чтобы в Registry не хранились абсолютно одинаковые по содержимому образы под разными именами. На последнем этапе Heroku загрузил локально собранный образ в Registry.

Шаг 5: Публикуем

Мы сделали все необходимое. Осталось попросить Heroku запустить контейнер и открыть к нему доступ через Интернет. Выполним команду:

heroku container:release web

Heroku опубликует последний добавленный в Registry образ приложения web.

Шаг 6: Любуемся

После завершения публикации приложение можно посмотреть в Интернете. В терминале напишем:

heroku open

Должна открыться страница в браузере с опубликованным приложением:

Шаг 7: Дополняем

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

heroku container:push web
heroku container:release web

5 — Исправляем ошибки

Если на странице вашего сервиса появилось сообщение об ошибке, можно посмотреть ее детали, написав в консоли:

heroku logs --tail

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

Какие проблемы могут возникнуть при публикации?

Проблема 1: Приложение не смогло подключиться к выделенному ему порту в течении 60 секунд:

Решение: Необходимо проверить, что содержимое файла heroku_config.yaml соответствует приведенному в статье, а в частности строкаport: $PORT.

Проблема 2: Python попытался выполнить миграции, но не смог получить доступ к базе данных:

Решение: Проверить, что вы действительно подключили дополнение PostgreSQL в Heroku. Если с дополнением все в порядке, тогда необходимо проверить, что heroku_config.yaml существует и соответствует примеру в статье.

Проблема 3: Приложение не смогло запуститься из-за ошибки при настройке:

Решение: Ошибка скорее всего воспроизведется при локальном запуске приложения. Изучив локальные логи или логи Heroku, необходимо исправить ошибку.

Проблема 4: произошла программная ошибка, детали ошибки будут описаны в выведенных логах:

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

6 — Вместо заключения

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

В ходе этой статьи мы:

  • Добавили конфигурационный файл для другого окружения и научились подменять его при публикации

  • Использовали Docker и Docker-compose для упаковки нашего приложения в контейнер

  • Создали приложение на Heroku и подключили к нему базу данных

  • Опубликовали наш сервис в Интернете

Исходный код для третьей части цикла статей можно найти в этом репозитории.

Полный цикл статей «Первые шаги в aiohttp»: 


Другие наши статьи по бэкенду и асинхронному программированию для начинающих:

Другие наши статьи по бэкенду и асинхронному программированию для продвинутого уровня:


? Как разобраться в асинхронном программировании на Python?

Асинхронный подход в Python реализуется через модуль Asyncio — это стандартная возможность языка. Если разработчик планирует развиваться в профессии и браться за более сложные задачи, рано или поздно ему придётся освоить Asyncio. Лучше рано :)

Разобраться в асинхронных принципах работы систем и научиться применять их на практике, можно на нашем курсе по асинхронному программированию на Python. В течение курса мы рассмотрим теорию работы асинхронных инструментов вообще и в Python в частности, а также напишем телеграм-бота и event loop.

? Посмотреть программу: https://vk.cc/cmUy1v

Теги:
Хабы:
Всего голосов 5: ↑5 и ↓0+5
Комментарии0

Публикации

Информация

Сайт
kts.tech
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия