Movies - это backend для онлайн кинотеатра, предоставляющий API с возможностями полнотекстового поиска.
Проект включает в себя набор сервисов:
adminpanel
- админка для управления библиотекой кинотеатра на Django;content
- асинхронный API-сервис выдачи контента с возможностями полнотекстового поиска.FastAPI
+Elasticsearch
+Redis
;etl
- сервис для переноса данных из SQLite в PostgreSQL и из PostgreSQL в Elasticsearch.
Полностью в докере с удобными sh скриптами для инициализации, линтинга, форматинга, а также набор коротких и часто используемых команд в Makefile.
- ✨ Особенности
- 🛠️ Функционал сервиса
- 🏗️ Архитектура решения
- 🚀 Быстрый старт
- 💻 Режим разработки
- 🚀 Запуск проекта
- 📝 Особенности разработки
✨ Особенности 🔝
- Поддерживает Python 3.11+;
- Полная Docker интеграция:
- тонкие образы - multi-stage сборка;
- docker-compose для локальной разработки;
- тесты в Docker;
- Django 4 + PostgreSQL:
- API на Django Rest Framework;
- Удобные настройки с django-split-settings;
- Отдельная схема
content
в базе данных. Схемаpublic
только для стандартныхDjango
таблиц; - Демобаза фильмов и сериалов;
- FastAPI + Elasticsearch + Redis - API для выдачи контента:
- полностью асинхронный;
- OpenAPI документация;
- Elasticsearch для полнотекстового поиска;
- Redis для кэширования;
- CI - workflow для GitHub Actions:
- SOLID код;
- ETL процессы для переноса данных между базами;
- Celery для управления расписанием запуска ETL процессов;
- Pydantic + python-dotenv для управления настройками;
- src-шаблон - отдельный пакет для каждого сервиса;
- Удобные sh скрипты:
🛠️ Функционал сервиса 🔝
Сервис предоставляет следующий функционал:
- База данных для фильмов, жанров, актеров (
PostgreSQL
); - Админка для управления контентом онлайн-кинотеатра (
Django
); - Заполненная база данных фильмов и сериалов (
SQLite
):- 5000+ персон (актеры, режиссеры, продюсеры);
- 1000+ кинопроизведений;
- 30+ жанров;
- API-сервис для выдачи контента (
FastAPI
+Elasticsearch
+Redis
):- полностью асинхронный;
- полное API для получения фильмов, жанров, персон;
- полнотекстовый поиск по фильмам и персонам;
- подробная документация API в формате
OpenAPI
;
- ETL процессы для переноса данных:
- from
SQLite
toPostgreSQL
; - from
PostgreSQL
toElasticsearch
;
- from
- Запуск ETL процессов по расписанию с помощью
Celery
.
Подробную документацию API можно посмотреть по адресу: http://localhost/api/v1/openapi
🏗️ Архитектура решения 🔝
🚀 Быстрый старт 🔝
Все команды, приведенные в данном руководстве, выполняются из корневой директории проекта, если иное не указано в описании конкретной команды.
⚙️ Настройка переменных окружения 🔝
Перед стартом, нужно создать файл .env
в корне проекта. Это можно сделать, выполнив команду:
make env
Можно просто скопировать файл env.template
.
🏁 Запуск 🔝
🚨 Убедись, что у тебя свободны все порты, указанные в настройках, оканчивающихся на _PORT
в файле .env
.
🚨 Укажи свою платформу для docker образов в настройке DOCKER_IMG_PLATFORM
в файле .env
.
Например, для Mac на M1 вот так:
DOCKER_IMG_PLATFORM=linux/arm64
Запустить проект в докере:
make run
Приложение adminpanel
будет доступно по адресу http://localhost:8000.
Приложение content
будет доступно по адресу http://localhost.
Документация API для приложения content
доступна по адресу: http://localhost/api/v1/openapi.
Запустить тесты в докере:
make tests-docker
Запустить заполнение баз подготовленными демо-данными:
make demo
Остановить и удалить все запущенные контейнеры:
make down
💻 Режим разработки 🔝
📚 Pre requirements 🔝
Для успешного развертывания среды разработки понадобится:
- Python ^3.11;
- Менеджер пакетов Poetry;
- Docker (version ^23.0.5). Если у тебя его еще нет, следуй инструкциям по установке;
- Docker compose (version ^2.17.3). Обратись к официальной документации для установки;
- Pre-commit.
Также будет полезным:
- Hadolint - линтер докер файлов.
🌐 Создание среды разработки 🔝
Перед выполнением команд из этого раздела, убедись, что у тебя установлены все компоненты Pre requirements, в противном случае, смотри инструкции по установке в подразделах ниже.
Для создания среды разработки, выполни следующие команды одну за другой, из корневой директории проекта:
make env
poetry shell
make init
Те же команды без Makefile
:
cp .env.template .env
cp .env.local.template .env.local
poetry shell
poetry install
pre-commit install
pre-commit install --hook-type commit-msg
📖 Установить Poetry 🔝
Подробнее про установку Poetry здесь.
Linux, macOS, Windows (WSL)
curl -sSL https://install.python-poetry.org | python3 -
Важно: после установки, необходимо добавить путь к Poetry в свой PATH
. Как правило, это делается
автоматически. Подробнее смотри в разделе Add Poetry to your PATH.
Проверить, что Poetry установлен корректно:
poetry --version
# Poetry (version 1.5.0)
🐳 Подробнее про Docker 🔝
Проект полностью интегрирован в docker
. Для локальной разработки используется docker-compose
.
Проект содержит следующие файлы docker-compose:
- docker-compose.yml - главный файл;
- docker-compose.dev.yml - содержит только изменения относительно главного файла, необходимые для режима разработки;
- docker-compose.test.yml - содержит только изменения для запуска тестов;
Файл docker-compose.yml 🔝
Файл docker-compose.yml
- это главный compose-файл. Любая команда docker-compose
должна использовать
этот файл в качестве первого аргумента.
Файл содержит все сервисы проекта (кроме тестовых) и основные метаданные для каждого сервиса,
такие как build
, env_file
, depends_on
и т.п.
Файл docker-compose.yml
не должен содержать портов, смотрящих наружу для сервисов баз данных.
Профили 🔝
Все сервисы в файле docker-compose.yml
сгруппированы по профилям. Профили необходимы для возможности
запуска только определенной группы сервисов.
Главный профиль - default
, все сервисы должны иметь этот профиль.
Существуют следующие профили:
default
adminpanel
content
etl
Например, к профилю adminpanel
относятся только сервисы postgres
и приложение adminpanel
и больше ничего.
Запустить исключительно сервис adminpanel
можно так:
make run-adminpanel
Файл docker-compose.dev.yml 🔝
Файл docker-compose.dev.yml
используется для запуска проекта в режиме разработки. Здесь добавляются
изменения относительно docker-compose.yml
. Например, здесь можно примонтировать тома для папок приложения
и указать порты, смотрящие наружу, чтобы облегчить отладку.
Файл docker-compose.test.yml 🔝
Файл docker-compose.test.yml
содержит сервисы только для тестов. Этот файл используется для запуска
тестов в докере.
🔄 Окружения dev и prod 🔝
Основной тип запуска проекта - через docker-compose. Запуск проекта может быть выполнен в одном
из двух окружений: development
или production
. Окружение управляется настройкой ENVIRONMENT
в
файле .env:
ENVIRONMENT=development
Если настройка ENVIRONMENT
имеет значение production
, то при запуске используется файл
docker-compose.yml. Если настройка ENVIRONMENT
имеет значение development
, то при
запуске используется дополнительный файл docker-compose.dev.yml.
При запуске в режиме development
папка приложения src монтируется как том, а каждый сервис
имеет expose
порты:
services:
adminpanel:
restart: "no"
volumes:
- ./src/${ADMINPANEL_PKG_NAME}:/${CONTAINER_WORK_DIR}/src/${ADMINPANEL_PKG_NAME}
postgres:
restart: "no"
ports:
- ${POSTGRES_PORT}:5432
📜 Один Dockerfile для двух окружений 🔝
Стоит обратить внимание на Dockerfile для сервисов Adminpanel
и Content
.
Помимо multistage
сборки, данный файл использует слои development
и production
в соответствии с
настройкой ENVIRONMENT
:
# ./docker/adminpanel/Dockerfile
ARG env=production
...
FROM final as development
FROM final as production
COPY ./src/${pck_name} ./src/${pck_name}
FROM ${env}
ENTRYPOINT ["./scripts/entrypoint.sh"]
Данная конфигурация позволяет использовать разные итоговые образы в зависимости от режима запуска. При запуске
в режиме development
папка приложения src монтируется как том в файле docker-compose.dev.yml,
поэтому слой development
в Dockerfile
пустой:
# ./docker/adminpanel/Dockerfile
...
FROM final as development
...
При запуске в окружении production
папка приложения src копируется с помощью инструкции COPY
:
# ./docker/adminpanel/Dockerfile
...
FROM final as production
COPY ./src/${pck_name} ./src/${pck_name}
В конце файла, выбирается образ из переменной env
:
# ./docker/python/Dockerfile
ARG env=production
...
FROM ${env}
Переменная env
в свою очередь передается как аргумент сборки:
# ./docker-compose.yml
services:
adminpanel:
build:
context: .
dockerfile: ./docker/${ADMINPANEL_PKG_NAME}/Dockerfile
args:
env: ${ENVIRONMENT}
Итоговый образ будет использовать самый последний слой. Таким образом, если настройка ENVIRONMENT
имеет
значение development
, то будет использован образ development
, а если production
, то production
.
🚀 Запуск проекта 🔝
Файл docker-compose.yml использует профили, что позволяет запускать отдельные наборы
сервисов. Основной профиль - это default
, он указан для всех сервисов.
Запустить все сервисы проекта:
make run
Команда make run
автоматически определяет режим запуска из настройки ENVIRONMENT
.
Посмотреть все запущенные сервисы:
docker-compose ps
Нативная команда для запуска в окружении development
:
docker-compose -f docker-compose.yml -f docker-compose.dev.yml --profile default up -d --build
Нативная команда для запуска в окружении production
:
docker-compose --profile default up -d --build
👨💼 Запуск сервиса Adminpanel 🔝
Запустить сервис Adminpanel в докере (--profile adminpanel
):
make run-adminpanel
При запуске сервиса Adminpanel в докере, автоматически запускаются миграции базы данных и создается суперюзер по настройкам из файла .env:
SUPERUSER_LOGIN=admin
SUPERUSER_EMAIL=admin@admin.com
SUPERUSER_PASSWORD=1
Для локального запуска сервиса Adminpanel нужно сначала запустить контейнер с базой данных:
make run s="postgres"
Создать миграции и выполнить их:
make migrate
Запустить только создание миграций:
make db-update
Нативная команда:
python src/adminpanel/manage.py makemigrations
Запустить только выполнение миграций:
make migrate
Нативная команда:
python src/adminpanel/manage.py migrate
Создать суперюзера:
make su
Нативная команда:
python src/adminpanel/manage.py create_superuser
Запустить сервис Adminpanel локально:
make adminpanel
Нативная команда:
python src/adminpanel/manage.py runserver
📝 Запуск сервиса Content 🔝
Запустить только сервис Content (--profile content
):
make run-content
Для локального запуска сервиса Content нужно сначала запустить контейнеры elasticsearch
и redis
.
Это можно сделать, запустив сервисы для профайла etl
:
make run-etl
Запустить приложение FastAPI
локально:
make content
Нативная команда:
python src/content/main.py
🔄 Запуск ETL процессов 🔝
Запустить контейнеры, необходимые для ETL процессов (--profile etl
):
make etl
Запустить ETL процесс для загрузки подготовленных демо-данных из SQLite
в PostgreSQL
:
make sql-to-pg
Нативная команда:
python src/etl/sqlite_to_pg.py
Запустить ETL процесс для переноса данных из PostgreSQL
в Elasticsearch
:
make pg-to-es
Нативная команда:
python src/etl/pg_to_es.py
🔧 Полезные команды 🔝
Запустить несколько определенных сервисов:
make run s="postgres redis"
Зайти внутрь контейнера:
make bash
Далее ввести имя контейнера - тоже что и имя сервиса.
Посмотреть логи сервиса:
make logs
Далее ввести имя контейнера - тоже что и имя сервиса.
Остановить все сервисы и удалить контейнеры:
make down
Посмотреть текущий конфиг docker-compose
:
make config
Удалить все неиспользуемые образы, контейнеры и тома:
make remove
📝 Особенности разработки 🔝
При разработке необходимо придерживаться установленных правил оформления кода. В этом разделе ты найдешь описание настроек редактора кода, линтеры и форматеры, используемые в проекте, а также другие особенности, которые необходимо учитывать при разработке.
🔗 Управление зависимостями 🔝
В качестве пакетного менеджера используется Poetry.
Для управления зависимостями используются группы (см. файл pyproject.toml
).
🚨 Важно: каждая зависимость должна принадлежать только одной группе. Нельзя добавлять одну и ту же зависимость в разные группы.
Если одна зависимость используется для различных сервисов, то она добавляется в дефолтную группу
tool.poetry.dependencies
.
Все основные зависимости располагаются в дефолтной группе tool.poetry.dependencies
:
[tool.poetry.dependencies]
python = "^3.11"
pydantic = "^1.10.2"
backoff = "^2.2.1"
Добавление основной зависимости:
poetry add pendulum
Остальные зависимости делятся на группы. Например, группа adminpanel
- зависимостей для сервиса Adminpanel:
[tool.poetry.group.adminpanel.dependencies]
Django = "^4.1"
...
Добавление общей зависимости:
poetry add pytest
Добавление зависимости в конкретную группу (используй флаг --group
и название группы):
poetry add pytest --group=test
Разделение зависимостей на группы позволяет уменьшить размер докер образов, так как в образы устанавливаются
только необходимые зависимости. Например, в образ сервиса Adminpanel будут установлены только зависимости
из группы adminpanel
и дефолтной группы tool.poetry.dependencies
:
# ./docker/adminpanel/Dockerfile
...
RUN poetry config virtualenvs.in-project true \
&& poetry install --only main,adminpanel
📝 Conventional Commits 🔝
Твои комментарии к коммитам должны соответствовать Conventional Commits.
Pre-commit хук conventional-pre-commit
выполнит проверку комментария перед коммитом.
Если твой комментарий не соответствует конвенции, то в терминале ты увидишь подобное сообщение:
commitizen check.........................................................Failed
- hook id: commitizen
- exit code: 14
commit validation: failed!
please enter a commit message in the commitizen format.
Для более удобного написания комментариев к коммитам, ты можешь воспользоваться плагином Conventional Commit для PyCharm:
🖥️ Настройки IDE 🔝
Проект содержит файл .editorconfig
- ознакомься с ним, чтобы узнать какие настройки
должны быть в твоем редакторе.
Основное:
- максимальная длина строки: 110;
- отступы: пробелы;
- количество отступов: 4.
🖊️ Форматер и линтер 🔝
В качестве форматера мы используем black.
Конфиг black см. в файле pyproject.toml
в секции [tool.black]
.
Линтер - flake8, конфиг находится в файле setup.cfg
.
Если ты используешь PyCharm, то можешь настроить форматирование файла с помощью black через External Tools:
Также можно повесить на это действие hot key: