Обслуживание приложений Flask с помощью uWSGI и Nginx в Ubuntu 16.04

Данное руководство поможет настроить простое приложение Python в микрофреймворке Flask на сервере Ubuntu 16.04. Также оно охватывает настройку сервера приложений uWSGI и обратного прокси-сервера Nginx.

Требования

  • Сервер Ubuntu 16.04.
  • Пользователь с доступом к sudo.
  • Базовые знания спецификации WSGI.

1: Установка компонентов из репозиториев Ubuntu

Для начала нужно установить все зависимости из репозиториев: pip (пакетный менеджер Python), инструменты разработки и веб-сервер Nginx.

Обновите индекс пакетов и установите все необходимые пакеты:

Если вы используете Python 2, введите:

sudo apt-get update
sudo apt-get install python-pip python-dev nginx

В Python 3:

sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx

2: Создание виртуальной среды

Теперь нужно изолировать приложение Flask от других файлов Python. Для этого используется виртуальная среда (virtual environment). Чтобы создать такую среду, установите инструмент virtualenv:

В Python 2:

sudo pip install virtualenv

В Python 3:

sudo pip3 install virtualenv

Теперь нужно создать и открыть родительский каталог проекта Flask:

mkdir ~/myproject
cd ~/myproject

Создайте виртуальную среду для хранения файлов проекта Flask:

virtualenv myprojectenv

Эта команда установит локальную копию Python и pip в каталоге myprojectenv.

Теперь включите виртуальную среду:

source myprojectenv/bin/activate

Командная строка изменится:

(myprojectenv)user@host:~/myproject$

Это значит, что среда включена.

3: Создание приложения Flask

Включив виртуальную среду, можно установить Flask и Gunicorn, а затем приступить к разработке приложения.

Установка Flask и uWSGI

Установить приложения Flask и uWSGI можно при помощи пакетного менеджера pip.

Примечание: Вне зависимости от версии Python следует использовать команду pip, а не pip3.

pip install gunicorn flask

Создание приложения

Теперь создайте простое приложение Flask.

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

Для примера создайте приложение, состоящее из одного файла, myproject.py:

nano ~/myproject/myproject.py

В этом файле будет храниться код приложения. Сюда нужно импортировать Flask и задать значение объекта Flask. Так можно определить функции, которые нужно выполнить при запросе определённых маршрутов.

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')

Этот код определяет, какой контент выводить при запросе корневого домена. Сохраните и закройте файл.

Если вы следовали руководству по начальной настройке сервера Ubuntu 16.04, вы заблокировали все порты при помощи брандмауэра UFW. Теперь нужно открыть порт 5000, иначе приложение не будет работать. Для этого введите:

sudo ufw allow 5000

Протестируйте приложение Flask:

python myproject.py

Откройте домен или IP в браузере, добавив номер порта, указанный в выводе в терминале (как правило, это :5000).

http://server_domain_or_IP:5000

На экране появится:

Hello There!

Чтобы остановить сервер разработки, нажмите CTRL-C в окне терминала.

Создание точки входа WSGI

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

Создайте файл wsgi.py:

nano ~/myproject/wsgi.py

Этот файл очень прост; импортируйте Flask и запустите его:

from myproject import app
if __name__ == "__main__":
app.run()

Сохраните и закройте файл.

4: Настройка и тестирование сервера uWSGI

Итак, приложение готово.

Теперь нужно убедиться, что uWSGI может обслуживать страницы приложения.

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

uwsgi --socket 0.0.0.0:5000 --protocol=http -w wsgi:app

Откройте в браузере домен или IP-адрес сервера, указав порт :5000.

http://server_domain_or_IP:5000

На странице должно появиться:

Hello There!

Теперь можно остановить сервер приложений, нажав в окне терминала CTRL-C.

Приложение готово, можно отключить виртуальную среду:

deactivate

Теперь все операции будут выполняться в общей среде Python.

Создание конфигурационного файла uWSGI

Сервер uWSGI может обслуживать приложение. Теперь нужно создать конфигурационный файл, в котором будут храниться постоянные настройки сервера.

Создайте файл myproject.ini в каталоге проекта:

nano ~/myproject/myproject.ini

Добавьте раздел [uwsgi], в нём укажите точку входа:

[uwsgi] module = wsgi:app

Затем настройте запуск uWSGI в режиме master. При этом будет запускаться пять рабочих процессов.

[uwsgi] module = wsgi:app
master = true
processes = 5

Во время тестирования для сервера uWSGI был открыт сетевой порт. Однако для обслуживания клиентских подключений будет использоваться веб-сервер Nginx, который, в свою очередь, будет передавать запросы серверу uWSGI. Поскольку оба эти компонента будут работать на одном компьютере, рекомендуется настроить поддержку более безопасных и быстрых Unix-сокетов. Поместите в каталог проекта сокет myproject.sock.

Затем нужно изменить права на файл сокета. В дальнейшем все права на процесс uWSGI нужно будет передать группе Nginx, потому владелец группы должен иметь права на чтение и запись сокета. Добавьте опцию vacuum, которая будет сбрасывать файл сокета после остановки процесса:

[uwsgi] module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true

В конец файла нужно добавить опцию die-on-term, благодаря которой система инициализации и uWSGI одинаково воспринимают сигналы процессов.

[uwsgi] module = wsgi:app
master = true
processes = 5
socket = myproject.sock
chmod-socket = 660
vacuum = true
die-on-term = true

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

5: Создание unit-файла systemd

После этого нужно создать файл сервиса для системы инициализации systemd. Такой файл позволяет системе инициализации автоматически запускать uWSGI и обслуживать приложение Flask.

Создайте unit-файл с расширением .service в каталоге /etc/systemd/system:

sudo nano /etc/systemd/system/myproject.service

Добавьте раздел [Unit], который определяет метаданные и зависимости приложения. Внесите в него описание сервиса.

[Unit] Description=uWSGI instance to serve myproject
After=network.target

Затем нужно добавить раздел [Service]. В нем нужно указать пользователя и группу, с помощью которых будет запущен сервис. Передайте текущему пользователю права на процесс и соответствующие файлы. Также права должна иметь группа www-data, тогда веб-сервер Nginx сможет взаимодействовать с процессом uWSGI.

Далее нужно установить переменную PATH, чтобы система инициализации знала, где искать исполняемые файлы (в виртуальной среде). Systemd требует полного пути к исполняемым файлам uWSGI в виртуальной среде.

[Unit] Description=uWSGI instance to serve myproject
After=network.target
[Service] User=8host
Group=www-data
WorkingDirectory=/home/8host/myproject
Environment="PATH=/home/8host/myproject/myprojectenv/bin"
ExecStart=/home/8host/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

В завершение нужно добавить раздел [Install], который определяет, к чему должен подключиться сервис во время автозапуска.

[Unit] Description=uWSGI instance to serve myproject
After=network.target
[Service] User=8host
Group=www-data
WorkingDirectory=/home/8host/myproject
Environment="PATH=/home/8host/myproject/myprojectenv/bin"
ExecStart=/home/8host/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
[Install] WantedBy=multi-user.target

Cервис systemd готов. Сохраните и закройте файл.

Запустите сервис uWSGI и включите его автозапуск.

sudo systemctl start myproject
sudo systemctl enable myproject

6: Настройка обратного прокси-сервера Nginx

Теперь приложение uWSGI готово. Настройте Nginx для передачи запросов на сокет с помощью протокола uwsgi.

Создайте новый блок server в каталоге sites-available:

sudo nano /etc/nginx/sites-available/myproject

Добавьте блок server. Задайте порт, который должен прослушивать веб-сервер (в данном случае – стандартный порт 80) и укажите доменное имя или IP в директиве server_name.

server {
listen 80;
server_name server_domain_or_IP;
}

Затем нужно добавить блок location, который будет содержать файл uwsgi_params (в нем хранятся параметры uWSGI). Отправьте запрос настроенному сокету при помощи директивы uwsgi_pass:

server {
listen 80;
server_name server_domain_or_IP;
location / {
include uwsgi_params;
uwsgi_pass unix:/home/8host/myproject/myproject.sock;
}
}

Это всё, что нужно для обслуживания приложения. Сохраните и закройте файл.

Чтобы включить блок server, нужно создать символьную ссылку в каталог sites-enabled:

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

Проверьте синтаксис на наличие ошибок.

sudo nginx -t

Если ошибок нет, перезапустите Nginx:

sudo systemctl restart nginx

Теперь нужно снова изменить настройки брандмауэра. Порт 5000 больше не используется, его можно заблокировать. Вместо этого нужно разблокировать доступ к Nginx.

sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'

Теперь откройте в браузере доменное имя или IP.

http://server_domain_or_IP

На странице появится:

Hello There!

Примечание: После настройки обратного прокси-сервера Nginx настоятельно рекомендуется защитить подключения при помощи сертификатов SSL/TLS. В противном случае все данные будут передаваться в виде простого текста и легко могут быть перехвачены злоумышленниками. Сервис Let’s Encrypt позволяет получить бесплатный сертификат. Подробнее об этом – здесь.

Заключение

Flask – очень простой, но чрезвычайно гибкий фреймворк.

Теперь на сервере есть полностью рабочее простое приложение Flask, хранящееся в виртуальной среде Python. Можно использовать его как шаблон для разработки более сложных приложений.

Tags: , , , , ,

Добавить комментарий