Фреймворк Flask — очень распространенное решение для разработки веб-приложений на Python. В production используется обычно связка flask uwsgi Nginx.
Фреймворк Flask, настройка работы Flask uwsgi Nginx
Рассмотрим настройку сервера для приложения на Flask. Простой проект будем создавать с нуля.
Установим нужные пакеты
apt-get install python3-dev nginx python3-pip
Запускается проект в виртуальном окружении (про virtualenv), позволяющем создавать настройки для каждого приложения и не использовать системные версии пакетов
pip3 install virtualenv
Скрипты разместим в отдельном каталоге
mkdir /home/todolist
Создаем одноименное окружение
virtualenv todolist
Оно будет представлять собой каталог todolist с определенной структурой внутри
Активируем окружение
source todolist/bin/activate
(todolist) root@server:/home/todolist#
Его имя теперь отображается в консоли. Можно устанавливать пакеты.
Создание простого приложения на фреймворке Flask
pip install uwsgi flask
Каталог /home/todolist будет домашним для непривелегированного пользователя, добавляем пользователя
useradd todo -m -d /home/todolist/ -s /bin/bash
Теперь само приложение. Слово Hi! крупным шрифтом серого цвета.
mcedit app.py
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "<h1 style='color:grey'>Hi!</h1>" if __name__ == "__main__": app.run(host='0.0.0.0')
Его уже можно запустить вручную
python app.py
Так запускать проект в production не стоит, поскольку процесс может быть в любой момент завершен — например, OOM.
Для автоматического перезапуска используется wsgi. Создаем конфигурационный файл.
mcedit wsgi.py
from app import app if __name__ == "__main__": app.run()
Из существующего скрипта app.py импортируется функция app.
Приложение можно вновь запустить вручную, в этот раз уже через uwsgi
uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app
Здесь указан TCP сокет, протокол, конфигурационный файл (wsgi) и функция в нем (app). Протокол — http. Он используется с TCP сокетом. По умолчанию задействуется протокол uWSGI.
Убедившись в том, что то же содержимое выводится — деактивируем окружение.
deactivate
Добавляем конфигурационный файл с настройками uwsgi
mcedit todo.ini
[uwsgi] module = wsgi:app master = true processes = 5 socket = todo.sock chmod-socket = 660 vacuum = true die-on-term = true
Протокол в production будем исспользовать uWSGI (при ручном запуске был http). uWSGI — более быстрое и безопасное решение, он по умолчанию поддерживается Nginx.
HTTP следует выбирать только когда Nginx и uwsgi работают на разных машинах. При такой ситуации был бы указан socket 0.0.0.0:5000, protocol=http
Отказоустойчивости и автоматического запуска процесса пока нет. Для него потребуется конфигурационный файл init / upstart / systemd
В Ubuntu 18 и более современных дистрибутивах используется systemd, убеждаемся в этом
file /sbin/init
/sbin/init: symbolic link to /lib/systemd/systemd
Создаем Unit файл Systemd
mcedit /etc/systemd/system/todo.service
[Unit] Description=uWSGI instance to serve todolist After=network.target [Service] User=todo Group=www-data WorkingDirectory=/home/todolist Environment="PATH=/home/todolist/todolist/bin" ExecStart=/home/todolist/todolist/bin/uwsgi --ini todo.ini [Install] WantedBy=multi-user.target
Запускаем сервис
systemctl start todo
Сейчас уже через uwsgi приложение должно работать на UNIX сокете
systemctl status todo
[…skipped…]
Active: active (running)
[…skipped…]
Проверяем наличие сокета
ss -l | grep todo
u_str LISTEN 0 100 todo.sock 1210456 * 0
Конфигурация Nginx для Flask с uwsgi
Последний шаг — настройка проксирования запросов на создаваемый сокет. В Nginx задается имя сайта или IP адрес, порт (обычно 80). Также путь к сокету. Это может быть и TCP сокет.
mcedit /etc/nginx/sites-enabled/todo
server { listen 80; server_name todo.example.com; location / { include uwsgi_params; uwsgi_pass unix:/home/todolist/todo.sock; } }
Виртуальный хост нужно активировать
ln -s /etc/nginx/sites-availible/todo /etc/nginx/sites-enabled/
Затем проверяем конфигурацию и перезапускаем Nginx
nginx -t
nginx -s reload
Служба должна работать на порту 80
netstat -nltp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 29624/nginx: master
Устанавливаем нужного владельца на файлы приложения
chown todo -R /home/todolist/
Перезапускаем uwsgi сервис
systemctl restart todo
Настройки на этом завершены. Если возникает 502 ошибка — нужно проверить логи Nginx
tail /var/log/nginx/error.log
Если есть необходимость изменять Unit файл — всегда нужно перезапускать демон Systemd
systemctl daemon-reload
Деплой готового приложения
Для того чтобы развернуть настоящее приложение достаточно переименовать файл app.py
mv app.py app.py_example
В каталоге с проектом выполнить
git clone https://github.com/YOUR-REPO/task-runner-py.git
И перезапустить
systemctl restart todo
Если основной файл называется app.py и в нем присутствует одноименная функция — других настроек не требуется.
В результате получится работающее в production приложение. Оно устойчиво к любым нештатным ситуациям: OOM-ам, закончившемуся месту на диске и будет автоматически перезапускаться при аварийном завершении процесса.
Если проект переносится с другого сервера помимо установки uwsgi и flask потребуется поставить все, что указано в requirements.txt