Докеризация Flask с помощью Postgres, Gunicorn и Traefik

задняя часть

В этом руководстве мы рассмотрим, как настроить Flask с помощью Postgres и Docker. Для производства мы добавим Gunicorn, Traefik и Let’s Encrypt.

Настройки проекта

Сначала создайте каталог проекта.

Не стесняйтесь заменить virtualenv и Pip наPoetryилиPipenv. Для получения дополнительной информации см.Современная среда Python.

Затем создайте следующие файлы и папки.

будетFlaskДобавьте в _requirements.txt_.

Установите пакет из «services/web».

Далее давайте создадим простое приложение Flask в ___init.py___.

Затем, чтобы настроить инструмент CLI Flask для запуска и управления приложением из командной строки, добавьте следующее в _services/web/manage.py_.

Здесь мы создаем новыйFlaskGroupПример расширения обычного интерфейса командной строки командами, относящимися к приложению Flask.

Запустите сервер из каталога «web».

перейдите к127.0.0.1:5000, Тебе следует увидеть.

Выключите сервер, когда закончите. Выйдите из виртуальной среды и удалите ее тоже.

Docker

УстановитьDocker, если у вас его еще нет, добавьте файл Dockerfile в каталог «web».

Поэтому мы начинаем сslimизДокер-образЗапущено для Python 3.9.5. Затем мы устанавливаемРабочий списоки две переменные окружения.

  1. PYTHONDONTWRITEBYTECODE: запретить Python записывать файлы pyc на диск (эквивалентноpython -B опции).
  2. PYTHONUNBUFFERED: запретить Python буферизовать stdout и stder (эквивалентноpython -u опции)

Наконец, мы скопировали файл _requirements.txt_, установили зависимости и скопировали само приложение Flask.

оглядыватьсяDocker for Python Developers, чтобы узнать больше о структурированных файлах Docker и некоторых рекомендациях по настройке Docker для разработки на основе Python.

Затем добавьте файл _docker-compose.yml_ в корневой каталог проекта.

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

Создайте образ.

После создания образа запустите контейнер.

перейдите кhttp://127.0.0.1:5000/, еще раз, чтобы увидеть проверку правильности hello world.

Если не получилось, пройдитеdocker-compose logs -f, проверьте журналы на наличие ошибок.

Чтобы настроить Postgres, нам нужно добавить новый сервис в файл _docker-compose.yml_, установивFlask-SQLAlchemyи установитьPsycopg2.

Во-первых, в _docker-compose.yml_ добавьте файл с именемdbновый сервис.

Чтобы данные сохранялись за пределами срока службы контейнера, мы настраиваем том. Эта конфигурация поставитpostgres_dataПривяжите к каталогу "/var/lib/postgresql/data/" в контейнере.

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

ПроверятьСтраница Postgres Docker Hubв разделе «Переменные среды» для получения дополнительной информации.

Пожалуйста, обрати вниманиеwebНовая команда на вооружении.

while !</dev/tcp/db/5432; do sleep 1Продлится до тех пор, пока не запустится Postgres. Как только началось,python manage.py run -h 0.0.0.0бегать.

Затем добавьте новый файл с именем _config.py_ в каталог «проект», где мы определим специфичные для средынастроитьПеременная.

Здесь база данных основана на том, что мы только что определили.DATABASE_URLпеременные среды для настройки. Обратите внимание на значение по умолчанию.

Обновите __init__.py_, чтобы получать конфигурацию при запуске.

Добавьте в _requirements.txt_Flask-SQLAlchemyиPsycopg2.

Обновите _init__.py_ еще раз, чтобы создать новыйSQLAlchemyэкземпляр и определить модель базы данных.

использовать в модели базы данныхdataclassДекораторы помогают нам сериализовать объекты базы данных.

Наконец, обновите _manage.py_.

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

Создайте новый образ и запустите два контейнера.

Создайте таблицу.

Получение следующей ошибки?

бегатьdocker-compose down -v, удалите том вместе с контейнером. Затем пересоберите образ, запустите контейнер и примените миграции.

удостоверитьсяusersТаблица создана.

Вы можете проверить, был ли создан том, запустив .

Вы должны увидеть что-то вроде этого.

перейдите кhttp://127.0.0.1:5000. Проверка работоспособности показывает пустой список. Это потому, что мы не заполнилиusersповерхность. Давайте добавим исходную команду CLI в _manage.py_, которая будетusersдобавлен в таблицу пользователей.

Попробуй.

Перейдите снова кhttp://127.0.0.1:5000. Вы должны увидеть это сейчас.

Gunicorn

Двигаясь дальше, для производственной среды давайте добавим в файл требованийGunicorn, сервер WSGI производственного уровня.

Поскольку мы по-прежнему хотим использовать встроенный сервер Flask в процессе разработки, создайте новый файл компоновки в корне проекта с именем _docker-compose.prod.yml_ для производства.

Если у вас есть несколько сред, вы можете посмотреть на использованиеdocker-compose.override.ymlконфигурационный файл. Используя этот метод, вы должны добавить свою базовую конфигурацию в файл _docker-compose.yml_, а затем использовать файл _docker-compose.override.yml_ для переопределения этих параметров конфигурации в зависимости от среды.

Обратите внимание, что по умолчаниюcommand. Мы используем Gunicorn вместо сервера разработки Flask. мы тоже изwebУдалите том из обслуживания, так как он нам не нужен в производстве.

разработает контейнер (и связанный с ним том, используя флаг -v)закрытие.

Затем создайте производственный образ и запустите контейнер.

Создайте таблицу и примените начальное значение.

проверятьhello_flask_prodбаза данных иusersТаблицы создаются вместе. пройти тестhttp://127.0.0.1:5000/.

Аналогичным образом, если контейнер не запускается, передайтеdocker-compose -f docker-compose.prod.yml logs -f, проверьте журнал на наличие ошибок.

Рабочий Dockerfile

Создайте новый файл Dockerfile в каталоге «web» с именем _Dockerfile.prod_ для производственных сборок.

Здесь мы использовали Dockerмногоступенчатая сборкачтобы уменьшить размер конечного изображения. в основном,builder— это временный образ для создания колес Python. Затем эти колеса воспроизводятся на окончательном производственном изображении, в то время какbuilderИзображения отбрасываются.

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

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

Обновите файл docker-compose.prod.yml вwebСервисы, созданные с помощью _Dockerfile.prod_.

Попробуй.

Traefik

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

Впервые на Траефик? см. официальныйначинаяруководство.

Traefik vs Nginx:Traefik — это современный обратный HTTP-прокси и балансировщик нагрузки. его часто сравнивают сNginx, веб-сервер и обратный прокси. Поскольку Nginx — это прежде всего веб-сервер, его можно использовать для обслуживания веб-страницы, а также в качестве обратного прокси-сервера и балансировщика нагрузки. В целом, Traefik проще настроить и запустить, а Nginx — более полнофункциональный.

Traefik.

  1. Обратный прокси и балансировщик нагрузки
  2. пройти черезLet's Encrypt, который автоматически выпускает и продлевает SSL-сертификаты из коробки.
  3. Используйте Traefik для простых микросервисов на основе Docker.

Nginx.

  1. Веб-серверы, обратные прокси-серверы и балансировщики нагрузки
  2. чем Траефикнемного быстрееНемного
  3. Использование Nginx для сложных сервисов

Добавьте новую папку с именем «traefik» в каталог «services» со следующими файлами.

Теперь структура вашего проекта должна выглядеть так.

Добавьте следующее в _traefik.dev.toml_.

Здесь, поскольку мы не хотим подвергатьdbобслуживание, мы будемexposedByDefaultУстановить какfalse. Чтобы вручную открыть службу, мы можем добавить в файл Docker Compose"traefik.enable=true"Тег.

Далее обновите файл _docker-compose.yml_, чтобы нашwebУслуга обнаружена Traefik и добавлена ​​новаяtraefikСлужить.

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

  1. traefik.enable=trueПозволяет Traefik обнаруживать службу
  2. traefik.http.routers.flask.rule=Host(`flask.localhost`)когда запрос имеетHost=flask.localhost, запрос будет перенаправлен на этот сервис

уведомлениеtraefikОбъем внутри сервиса.

  1. ./services/traefik/traefik.dev.toml:/etc/traefik/traefik.tomlНапечатайте файл локального конфигурации в файл конфигурации в контейнере, поэтому настройки остаются в синхронизации
  2. /var/run/docker.sock:/var/run/docker.sock:ro, позволяя Traefik обнаруживать другие контейнеры.

Для тестирования сначала отключите все существующие контейнеры.

Создайте новый образ разработки и запустите контейнер.

Создайте таблицу и примените начальное значение.

перейдите кflask.localhost. Тебе следует увидеть.

Вы также можете протестировать через cURL.

Далее, вflask.localhost:8081,экзаменПриборная доска .

traefik dashboard

Закройте контейнер и объем, когда закончите.

давайте зашифруем

Мы успешно создали рабочий экземпляр Flask, Docker и Traefik в режиме разработки. Для производства вам необходимо настроить Traefik дляУправляйте сертификатами TLS с помощью Let's Encrypt. Короче говоря, Traefik автоматически связывается с центром сертификации для выдачи и обновления сертификатов.

Поскольку Let's Encrypt не будетlocalhost, вам нужен экземпляр облачных вычислений (например,DigitalOceanдроплеты или инстансы AWS EC2) для запуска ваших производственных контейнеров. Вам также необходимо действительное доменное имя. Если у вас его нет, вы можетеFreenomСоздайте бесплатное доменное имя.

Мы используемDigitalOceanDroplet и Docker Machine для быстрой подготовки вычислительных экземпляров Docker и развертывания производственных контейнеров для тестирования конфигурации Traefik. Ознакомьтесь с документацией Docker дляПример DigitalOcean, чтобы узнать больше о настройке дроплетов с помощью Docker Machine.

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

Сначала добавьте конфигурацию Traefik для производственной сборки в _traefik.prod.toml_.

Пожалуйста, убедитесь, что[[email protected]](https://testdriven.io/cdn-cgi/l/email-protection)Используйте свой реальный адрес электронной почты.

Что тут происходит.

  1. entryPoints.webУстановите точку входа нашего небезопасного HTTP-приложения на порт 80.
  2. entryPoints.websecureУстановите точку входа нашего безопасного HTTPS-приложения на порт 443.
  3. entryPoints.web.http.redirections.entryPointПеренаправить все небезопасные запросы на безопасные порты
  4. exposedByDefault = falseотменить все услуги
  5. dashboard = trueВключить панель мониторинга

Наконец, пожалуйста, обратите внимание.

Вот расположение конфигурации Let’s Encrypt. Мы определяем сертификатместо храненияместоположение иТип аутентификации, это,HTTP-вызов.

Далее предположим, что вы обновили записи DNS для своего доменного имени, создав две новые записи A, обе указывающие на общедоступный IP-адрес вашего вычислительного экземпляра.

  1. flask-traefik.your-domain.com- для веб-сервисов
  2. dashboard-flask-traefik.your-domain.com- для приборной панели Traefik

Обязательно замените на свое фактическое доменное имяyour-domain.com.

Затем обновите _docker-compose.prod.yml_ следующим образом.

Опять же, не забудьте заменить на ваше фактическое доменное имяyour-domain.com.

Что здесь нового?

существуетwebУслуги мы добавили следующие теги.

  1. traefik.http.routers.flask.rule=Host(`flask-traefik.your-domain.com`)Измените хост на фактическое доменное имя
  2. traefik.http.routers.flask.tls=trueВключить HTTPS
  3. traefik.http.routers.flask.tls.certresolver=letsencryptУстановите эмитента сертификата на Let's Encrypt

Далее, дляtraefikservice мы добавили соответствующий порт и том для каталога сертификатов. Этот том гарантирует, что сертификат сохраняется, даже если контейнер закрыт.

Что касается этикеток.

  1. traefik.http.routers.dashboard.rule=Host(`dashboard-flask-traefik.your-domain.com`)Хост панели мониторинга определен, поэтому к нему можно получить доступ$Host/dashboard/
  2. traefik.http.routers.dashboard.tls=trueВключить HTTPS
  3. traefik.http.routers.dashboard.tls.certresolver=letsencryptУстановите распознаватель сертификатов на Let's Encrypt
  4. traefik.http.routers.dashboard.middlewares=authвключитьHTTP BasicAuthпромежуточное ПО
  5. traefik.http.middlewares.auth.basicauth.usersОпределите имя пользователя и хешированный пароль для входа в систему

Вы можете использовать инструмент htpasswd для создания нового хэша пароля.

Не стесняйтесь использоватьenv_file, в котором имя пользователя и пароль хранятся как переменные среды

Обновите _Dockerfile.traefik_.

Затем раскрутите новый контейнер.

Создайте таблицу и примените начальное значение.

Убедитесь, что оба URL действительны.

  1. flask-traefik.your-domain.com
  2. dashboard-flask-traefik.your-domain.com/dashboard/

Кроме того, убедитесь, что при посещении HTTP-версии вышеуказанного URL-адреса вы перенаправляетесь на HTTPS-версию.

Наконец, сертификат Let's Encrypt действителен для90 дней. Trefik автоматически обрабатывает продление сертификата для вас за кулисами, поэтому вам не о чем беспокоиться

Суммировать

В этом руководстве мы рассмотрели, как контейнеризировать приложение Flask с помощью Postgres. Мы также создали готовый к работе файл Docker Compose, настроили Traefik и Let's Encrypt для обслуживания приложения через HTTPS и включили панель безопасности для мониторинга наших служб.

С точки зрения фактически развертывания до производства, вы можете использовать один.

  1. Полностью управляемые службы баз данных, такие какRDSилиCloud SQL--вместо управления собственным экземпляром Postgres в контейнере.
  2. пользователь службы без полномочий root

ты сможешьflask-docker-traefikНайдите эти коды в репозитории.