Зарегистрируйтесь, чтобы продолжить обучение

Деплой Python: Веб-разработка (Flask)

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

Конфигурация

Любое нетривиальное приложение взаимодействует с внешним миром: использует базу данных, обращается к внешним сервисам (например, платежным), отправляет письма и получает список друзей, например, из Facebook. Для подавляющего большинства этих операций необходимы специальные параметры: ключи, пароли, адреса серверов и порты. Все эти параметры называются конфигурацией приложения.

Возникает вопрос, где хранить конфигурацию? Самый простой и самый неправильный ответ – прямо в приложении. Проблем у такого подхода две:

  • Часть этих данных секретная. Хранить их в репозитории просто нельзя из-за возможных проблем с безопасностью. Любой кто имеет доступ к репозиторию сможет получить любой доступ.

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

В 2011 году разработчики компании Heroku выложили в интернете сайт, который называется 12factors. Он описывает методологию для создания веб-приложений. Она уменьшает затраты на установку и настройку приложения, повышает переносимость между средами исполнения, позволяет масштабироваться без существенных изменений в инструментах, архитектуре и практике разработки. С тех пор эта методология фактически стала стандартом в индустрии.

Рекомендуем полностью изучить этот документ. Сейчас же нас интересует один его аспект — конфигурация. Двенадцать факторов требуют строгого разделения конфигурации и кода. Конфигурация может меняться между развертываниями: локальное окружение разработчика, продакшен, среда для тестирования. Код не меняется.

Конфигурация должна передаваться в приложение снаружи. Единственный универсальный способ сделать это — использовать переменные окружения.

Переменные окружения

У Flask большое количество настроек для разных подсистем. Все они задаются в объекте app.config. Например, так можно запустить фреймворк в режиме отладки:

# При запуске устанавливается переменная DEBUG со значением True
app.config["DEBUG"] = True

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

Некоторые такие настройки конфиденциальны и должны храниться отдельно от основного кода проекта. Для этих целей используются переменные окружения:

import os
from flask import Flask

app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]

У данного способа есть несколько недостатков:

  • Переменные загружаются только из окружения
  • Необходимо обрабатывать исключения KeyError
  • Необходимо конвертировать типы вручную (например, DEBUG=True из строки в bool)

Для простоты конфигурации Flask можно использовать стороннюю библиотеку python-dotenv. Она позволяет загружать переменные не только из окружения, но и из специального файла .env, который находится в корне проекта. Этот файл не должен храниться в репозитории, ведь в нем конфидециальные данные: ключи, пароли. Он специфичен для окружения, в котором идет запуск. Вот его пример:

DEBUG=True
SECRET_KEY=your-secret-key
DATABASE_URL=sqlite:///my-local-sqlite.db
CACHE_URL=memcache://127.0.0.1:11211
REDIS_URL=redis://127.0.0.1:6379/1

Это обычный текстовый файл, в каждой строке которого находится имя переменной и ее значение. python-dotenv автоматически подгружает его, и затем эти переменные используются в коде, если это необходимо.

Чтобы подключить python-dotenv, необходимо в файле инициализации приложения (например, app.py) произвести следующие настройки:

from dotenv import load_dotenv  # Импортируем dotenv
import os

load_dotenv()  # Загрузка переменных окружения из файла .env

Теперь можно использовать переменные окружения, которые описаны в файле .env:

from flask import Flask
import os

app = Flask(__name__)

app.config["SECRET_KEY"] = os.getenv("SECRET_KEY")
app.config["DEBUG"] = os.getenv("DEBUG", "False") == "True"
app.config["DATABASE_URL"] = os.getenv("DATABASE_URL")

WSGI

Любое веб-приложение, которое написано с использованием Flask, является WSGI-приложением — Web Server Gateway Interface. Оно используется практически всеми веб-фреймворками для Python. Это соглашение об описании веб-приложения в виде обычной функции request -> response.

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

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

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

До этого момента мы запускали приложение с помощью команды flask. Эта команда запускает WSGI-приложение на упрощенном сервере разработчика. Этот сервер может обрабатывать только один запрос за раз и не позволяет запускать несколько интерпретаторов. При этом его не нужно настраивать, а приложение он умеет перезапускать сам, как только код будет изменен.

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

Gunicorn

Один из самых популярных WSGI-серверов — Gunicorn. Установим его в наш проект — в то же виртуальное окружение, в которое установили flask:

uv add gunicorn

Когда Gunicorn будет установлен, для запуска приложения вместо команды flask можно будет запустить приложение так:

uv run gunicorn --workers=4 --bind=127.0.0.1:8000 hello_world:app

Это пример типичной команды для запуска. Он показывает две самых важных опции Gunicorn:

  • Количество интерпретаторов, которые будут выполнять код приложения — воркеры
  • Адрес, запросы к которому и будет обслуживать сервер

Вот соответствующие опции в приведенной команде:

  • --workers=4 — использовать четыре воркера
  • --bind=127.0.0.1:8000 — слушать порт 8000 на хосте 127.0.0.1

WSGI-приложение указывается в виде полное.имя.модуля:переменная. Нужно указывать не имя файла, а имя модуля или пакета, который экспортирует переменную, ссылающуюся на WSGI-приложение — объект Flask.

Доставка приложений до сервера

Когда сайт написан, его нужно выложить в интернет. Стандартный путь включает три пункта:

  1. Покупка домена
  2. Покупка хостинга и его настройка
  3. Деплой

Рассмотрим эти пункты более подробно.

Покупка домена

Чтобы приобрести домен, необходимо обратиться в компании-регистраторы. Домен оплачивается раз в год и закрепляется за определенным человеком или компанией. Иногда хостер и регистратор — одна и та же компания. Тогда домен и сервер связываются одновременно. Иначе нужно производить определенные настройки на стороне сервера и подтверждать свое право владения доменом.

Покупка хостинга и его настройка

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

Обычно работа с хостингом выглядит следующим образом:

  1. Производится регистрации на сайте хостинга
  2. Выбирается подходящий тариф и вид хостинга (On-Prem, IaaS, PaaS, SaaS) и привязывается банковская карточка
  3. Предоставляется доступ к ресурсам, например, IP-адрес и пара логин/пароль для ssh- или ftp-доступа
  4. При необходимости производится настройка хостинга и деплой проекта

Деплой

Деплой — процесс выкладки новой версии сайта на сервер. Этот процесс может быть довольно сложным и зависит от используемых технологий. Во время деплоя могут выполняться следующие задачи:

  1. Код проекта скачивается на сервер — обычно через клонирование Git
  2. Ставятся все необходимые зависимости
  3. Выполняется процесс сборки, например, собирается фронтенд-часть
  4. Выполняются миграции — SQL-скрипты, которые изменяют структуру базы данных
  5. Запускается новая версия кода

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

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

Также деплои можно классифицировать по способу обновления и отката:

  • Последовательное обновление — сервера обновляются по очереди
  • Сине-Зеленый деплой — полное дублирование инфраструктуры с подменой

Отдельно стоит сказать про канареечный релиз — canary release. При таком подходе переключение на использование новой версии происходит постепенно — сначала для небольшого процента пользователей, а затем и для всех.

Способ деплоя зависит от используемого хостинга и способа настройки серверного окружения. Выделяют следующие типы хостингов:

  • Виртуальный хостинг (Shared Hosting) — самый дешевый способ размещать сайт в интернете. Такая услуга включает доступ на сервер с уже настроенным программным обеспечением под конкретный стек, например, Linux + Python + MySQL. Этот способ подходит для самых простых сайтов и требует минимальной настройки
  • VPS/VDS — наиболее сбалансированная услуга, в рамках которой предоставляется виртуальная машина. Плюс в том, что такой вид хостинга позволяет задействовать больше серверных мощностей: ЦПУ, память и диск. Предустановленного ПО нет, все нужно делать самостоятельно. По сравнению с виртуальным хостингом мы не ограничены в правах и можем настраивать сервер как угодно
  • Выделенный сервер (Dedicated Server) — сервер либо свой, либо арендованный. Такой хостинг требует больше всего участия, но зато мы получаем лучшее соотношение производительность/цена
  • IaaS (Infrastructure as a Service) — инфраструктура как сервис. Вид хостинга, при котором большая часть возможностей представляется как сервис, например, Amazon Web Service (AWS)
  • PaaS (Platform as a Service) — платформа как сервис. Наиболее дорогой и самый автоматизированный способ из коробки по размещению сайтов. Выкладка сайта происходит по команде git push. Кроме цены важно учитывать используемые технологии и подходы. PaaS обладает наибольшим числом ограничений по тому, что и как можно делать, но в обмен мы получаем не просто автоматизированный хостинг, но и платформу, которая автоматически масштабируется под нагрузку

Все способы деплоя можно разбить на две большие категории: деплой на PaaS и деплой на все остальное.

Деплой на PaaS

Самый простой способ начать деплоить. Большинство PaaS-хостеров имеют бесплатные планы, достаточные для публикации учебных проектов. Из плюсов: не придется покупать адрес, домен третьего уровня предоставляется бесплатно.

Самое популярное PaaS-решение на текущий день — Heroku. Также в качестве бесплатной альтернативы Heroku мы предлагаем Render. Он поддерживает деплой как из Github репозиториев, так и из локальных с помощью cli-утилиты.

Деплой на все остальное

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

Самая первая задача — настроить окружение. Если в виртуальном хостинге всегда есть набор предустановленных программ, то в остальных видах хостинга нет ничего, кроме голой операционной системы. Установка необходимого ПО такой же автоматизируемый процесс, как процесс деплоя, и у него есть даже собственное название — Управление конфигурациями (Configuration Management).

Рекомендуем использовать Ansible — популярное решение для настройки. На Хекслете есть соответствующий курс.

Ключевое понятие Ansible — Playbook (плейбук). Это файл или файлы в формате YAML. В них описывается, что нужно сделать на указанной машине. В каждом плейбуке используются готовые модули, которые поставляются вместе с Ansible. Этих модулей сотни, с помощью них можно делать практически всё: от установки программ до настройки сети и управления правами файловой системы.

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

- hosts: all

  tasks:

    - lineinfile:
        create: yes
        regexp: ~/.local
        path: ~/.bash_profile
        line: "export PATH=$PATH:~/.local/bin"

    - name: install packages
      apt: pkg=python3-pip state=latest update_cache=yes
      tags: pip
      become: yes

    - pip:
        name: pip
        state: latest
      become: yes

Ansible — универсальный инструмент, с его помощью можно не только настраивать окружение, но и деплоить. При этом для деплоя есть готовый модуль — deploy helper.

В более продвинутых случаях, там где используется, например, Docker, развертывание осуществляется системами оркестрации, среди которых выделяется Kubernetes.


Самостоятельная работа

Выложите на Render тот код, который вы написали в течение этого курса

Эталонный проект


Дополнительные материалы

  1. Среды разработки
  2. DevOps
  3. Непрерывное развертывание
  4. Terraform
  5. Ansible

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff