Создаем приложение: Docker, VueJs и Python-Sanic. Часть 1

В рамках статьи мы создадим одностраничное (SPA) приложение с использованием VueJs. Оно будет общаться с WebSocket-сервером, предварительно авторизировавшись через backend api. WebSocket-сервер и api реализуем при помощи фреймворка Sanic.

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

Кратко обо мне

Я вошел в веб 15 лет назад, во времена тотального доминирования PHP в качестве серверной платформы. Впоследствии я перешел на Python. Разработка web-приложений из монолитного кода начала «растекаться», сначало на серверную и интерфейсную части, потом стало модным растягивать по микросервисам еще и backend. Сейчас зачастую мне приходиться брать на себя роль бекенд- и фронтенд-разработчика. При этом сильно прокачиваются навыки DevOps, чтобы заставить кучу всего разрозненного работать вместе.

Стек, который я использую в работе сейчас:

  • Python framework: Flask; Sanic;
  • DB: PostgreSQL, Redis, RebbitMQ, MongoDB, MySQL;
  • JavaScript: VueJs, Jquery;
  • DevOps: Docker, Ansible.

Постановка задачи

Пишем приложение для http://localhost:

  1. По ссылке /db открывается web-клиент adminer для работы с PostgreSQL.
  2. По ссылке /app открывается web-клиент на VueJs, который содержит форму авторизации и после ее успешного выполнения позволяет получать/отправлять сообщения через webSocket.
  3. По ссылке /api реализовать API (python-Sanic):
    • авторизовывать пользователя из PostgreSQL;
    • данные сессии записывать в Redis.
  4. По ссылке /ws реализовать WebSocket server, принимающий запросы от авторизованного через API клиента и отвечающий ему.

Аргументация выбранного стека

Почему Redis? — Тут без комментариев.

Почему PostgreSQL? — Благодаря огромному опыту работы с MySQL, эмпирическим путем пришел к наиболее оптимальному решению.

Почему VueJs? — Не хотелось бы священных войн, изложу кратко свое видение. Для меня, как для fullstack разработчика с упором на backend, VueJs оказался весьма прост в освоении и понятен в своей концепции. Более популярные фреймворки React и особенно Angular имеют, на мой взгляд, несопоставимо более высокий порог вхождения. Они требуют гораздо больше времени на изучение и удержание достаточного уровня квалификации.

Почему backend на Sanic? — В среде Python в последнее время произошла довольно серьезная революция, связанная с развитием асинхронного программирования. У меня был опыт написания кода на Twisted и Tornado, но современная реализация async/await выше всяких похвал. Как грибы после дождя появились различные асинхронные веб-фреймворки. Но мой выбор пал на Sanic, потому как он практически полностью копирует интерфейсность Flask (в котором у меня наибольший опыт работы последних лет), при этом добавляет приложению огромную производительность и функциональность (тот же WebSockets).

Нюанс: Sanic еще весьма молод, под него мало пакетов. Производятся попытки миграции c Flask такого полезного расширения, как Restfull. На момент написания статьи там еще далеко даже до бета-релиза. Но, по моему мнению, сам фреймворк стабилен и великолепен — можно пользоваться.

Реализация и вводные данные

Мой рабочий компьютер:

Этап 1: Инициализация проекта

Этап 2. Как это все будет работать

Согласно постановки задачи, у нас есть 2 приложения: Redis, PostgreSQL, которые должны быть изолированы от доступа извне, но должны быть доступны для использования из Python. C другой стороны, есть 4 точки входа, которые коммуницируют с внешним миром, то есть доступны через браузер. Это /app, /api, /ws, /db -за каждым из этих интерфейсов стоит свой работающий процесс.

Для /app — это процесс webpack watcher, задача которого — остлеживать изменение кода, который мы будем вносить, и налету преобразовывать его при помощи подключенных плагинов (broserify, cssminify и т. д.) в исполняемый браузером код.

Для /api и /ws — это будет один общий python worker, который также будет отслеживать изменения и перезапускать самого себя.

Все вышеописанные правила довольно просто реализовать при помощи Nginx, проксируя URL-запросы к им соответствующим демонам, которые работают на выделенных портах.

Этап 3. Контейнеризация

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

Обращаю внимание, что этот файл лишь в рамках этой статьи был добавлен в Git-репозиторий. В реальной жизни ему не место в репозитории. На сервере этот файл создается ручками, со своими значениями переменных. Далее:

В конфигурации сервера мы декларируем запуск Nginx на 80-м порту. При этом все запросы, URL которых начинается с /db, перебрасываем на сервис adminer-а, который будет запущен на порту 8080. Я вынесу за рамки статьи информацию о том, что такое Docker, как связан с ним docker-compose и как это все работает. Ознакомиться с этими приложениями можно в официальной документации.

Перейдем непосредственно к реализации. На момент написания статьи версия 3.7 — последняя для спецификации содержимого docker-compose.yml. Ее и будем использовать:

Cети (networks)

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

Создавать разные сети для Dev-окружения совершенно нет необходимости. Но, как уже говорил выше, для одного разработчика хранить и актуализировать параллельно 2 сценария контейнеризации — излишняя трата времени. В рамках ограниченных ресурсов необходимо стараться делать окружение таким, каким оно будет выглядеть в продакшене с минимальными изменениями. Также можно оспорить необходимость делать веб-доступ к базе данных продакшена через adminer. Локально я предпочитаю коннектиться к базе через консоль, но иногда для оперативности — веб-доступ. Это экономит время.

Redis

Строки 9-15: стандартные инструкции создания Redis контейнера. Обратите внимание, что доступ к нему другие контейнеры могут получить из подсети «internal».

PostgreSQL

Строки 18-30: создаем контейнер на базе официального образа PostgreSQL. Обратите внимание на строки 23-25. По умолчанию перед запуском docker-compose автоматически читает переменные, заданные в .env файле, но не передает их дальше в контейнер для создания базы данных, пользователя и пароля. Для этой цели существует 2 способа. Первый — через переменную сервиса environment, где необходимо задать пару ключ-значение. Второй способ — через переменную env_file, когда мы пробрасываем все переменные файла .env непосредственно в контейнер (сделаем это чуть позже на примере серверного приложения).

В строке 29 мы «заставляем» базу данных хранить данные вне контейнера.
В строке 30 мы в момент создания контейнера запускаем SQL-инструкцию по созданию базы данных «test», которую будем использовать при написании тестов.

Adminer

Строки 33-39: поднимаем оффициальный Docker контейнер от Adminer. Обращаем внимание, что в конфигурации нужно явно указать сервис(ы), к которым он будет иметь доступ (в нашем случае это DB). Также указываем internal подсеть, по которой будет идти коммуникация.

Отступление. Наряду с Adminer на продакшене возможна контейнеризация любого другого множества вспомогательных приложений (скажем, redis-commander или phpMyAdmin). Рекомендую поднимать их в отдельной подсети, с доступом к ней только из-под VPN. Можно не заморачиваться с VPN, а ограничить доступ к определенным сервисам по IP, но такой подход менее гибок.

Строки 41-50: запускаем контейнер на базе официального образа Nginx, пробрасывая наш ранее созданный конфигурационный файл. Обратите внимание: необходимо указать связь с контейнером adminer через подсеть internal. Без этого указанный в server.conf сервис http://adminer:8080 доступен не будет.

В следующих частях статьи рассмотрим, как расширить файл server.conf, дополнить для работы с двумя другими сервисами app и api.

Этап 4. Построение и запуск контейнеров

На этапах 1-3 мы полностью подготовили необходимое для разработки окружения. Осталось запустить все и проверить, как это работает.

Теперь:

Открываем в браузере http://localhost/db и видим страницу входа в Adminer. Логинимся в базу данных при помощи значений переменных файла .env. Убеждаемся, что выполнился скрипт из директории db_entrypoint/, создавший базу test.

Итог

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

После чего пробуйте зайти на localhost/db.

Продолжение следует...

Похожие статьи:
В этой статье я расскажу о процессе вступления в жизнь студента айтишной специальности. Написана она не только для детей — тщу себя...
27 февраля в Киеве стартует курс для IT-специалистов от Brain Academy — Agile Thinking! Существует множество тренингов, которые обучают механике...
По данным ресурса Business Insider, компания Apple может продать порядка 2,5 или 3 миллионов планшетов iPad Pro. Это гораздо меньше цифр о которых...
Furniture refers tо movable оbjесtѕ intеndеd to ѕuрроrt vаriоuѕ humаn асtivitiеѕ such as ѕеаting (e.g., сhаirѕ, stools, аnd sofas), eating (tаblеѕ), and ѕlеерing (е.g., bеdѕ). Furniturе iѕ аlѕо...
Image via Shutterstock.[Об авторе: Алексей Витченко — серийный предприниматель, имеет более 10 лет опыта в digital, e-commerce на западных рынках....
Яндекс.Метрика