Поиск по сайту:

Как обслуживать приложения Flask с помощью Gunicorn и Nginx в Ubuntu 18.04


Введение

В этом руководстве вы создадите приложение Python с использованием микрофреймворка Flask в Ubuntu 18.04. Основная часть этой статьи будет посвящена тому, как настроить Nginx для работы в качестве внешнего обратного прокси-сервера.

Предпосылки

Для выполнения этого урока вам понадобятся:

  • Сервер с установленной Ubuntu 18.04, пользователем без полномочий root с привилегиями sudo и включенным брандмауэром. Следуйте нашему руководству по первоначальной настройке сервера.
  • Nginx установлен, следуя шагам 1 и 2 инструкции по установке Nginx в Ubuntu 18.04.
  • Доменное имя, настроенное так, чтобы оно указывало на ваш сервер. Вы можете приобрести его в документации по доменам и DNS. Обязательно создайте следующие записи DNS:
    • Запись A с your_domain, указывающая на общедоступный IP-адрес вашего сервера.
    • Запись A с www.your_domain, указывающая на общедоступный IP-адрес вашего сервера.

    Знакомство со спецификацией WSGI, которую сервер Gunicorn будет использовать для связи с вашим приложением Flask. В этом обсуждении WSGI рассматривается более подробно.

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

    Первый шаг — установить все необходимые пакеты из стандартных репозиториев Ubuntu. Это включает в себя pip, менеджер пакетов Python, который будет управлять вашими компонентами Python. Вы также получите файлы разработки Python, необходимые для создания некоторых компонентов Gunicorn.

    Сначала обновите локальный пакет:

    1. sudo apt update

    Затем установите пакеты, которые позволят вам создать среду Python. К ним относятся python3-pip, а также еще несколько пакетов и инструментов разработки, необходимых для надежной среды программирования:

    1. sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

    Имея эти пакеты, переходите к созданию виртуальной среды для вашего проекта.

    Шаг 2 — Создание виртуальной среды Python

    Затем настройте виртуальную среду, чтобы изолировать ваше приложение Flask от других файлов Python в системе.

    Начните с установки пакета python3-venv, который установит модуль venv:

    1. sudo apt install python3-venv

    Затем создайте родительский каталог для вашего проекта Flask:

    1. mkdir ~/myproject

    Затем перейдите в каталог после его создания:

    1. cd ~/myproject

    Создайте виртуальную среду для хранения требований Python вашего проекта Flask, введя следующее:

    1. python3.6 -m venv myprojectenv

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

    Перед установкой приложений в виртуальной среде вам необходимо активировать ее, выполнив следующее:

    1. source myprojectenv/bin/activate

    Ваше приглашение изменится, чтобы показать, что вы сейчас работаете в виртуальной среде. Это будет выглядеть следующим образом:

    (myprojectenv)\ssammy@host:~/myproject$
    

    Шаг 3 — Настройка приложения Flask

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

    Сначала установите wheel с локальным экземпляром pip, чтобы убедиться, что ваши пакеты будут установлены, даже если в них отсутствуют архивы колес:

    1. pip install wheel

    Примечание. Независимо от используемой версии Python при активации виртуальной среды следует использовать команду pip (не pip3).

    Затем установите Flask и Gunicorn:

    1. pip install gunicorn flask

    Теперь, когда у вас есть Flask, вы можете создать базовое приложение на следующем шаге.

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

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

    Хотя ваше приложение может быть более сложным, мы создадим наше приложение Flask в одном файле с именем myproject.py. Создайте этот файл с помощью предпочитаемого вами текстового редактора; здесь мы будем использовать nano:

    1. 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')
    

    Это определяет, какой контент будет отображаться при доступе к корневому домену. Сохраните и закройте файл, когда закончите. Если вы используете nano, вы можете сделать это, нажав CTRL + X, затем Y и ENTER.

    Если вы следовали руководству по первоначальной настройке сервера в предварительных требованиях, у вас должен быть включен брандмауэр UFW. Для тестирования приложения сначала необходимо разрешить доступ к порту 5000:

    1. sudo ufw allow 5000

    Затем вы можете протестировать свое приложение Flask, выполнив следующее:

    1. python myproject.py

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

    Output
    * Serving Flask app 'myproject' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on all addresses. WARNING: This is a development server. Do not use it in a production deployment. * Running on http://your_server_ip:5000/ (Press CTRL+C to quit)

    Посетите IP-адрес вашего сервера, а затем :5000 в веб-браузере:

    http://your_server_ip:5000
    

    Вы должны получить что-то вроде следующего:

    Когда вы закончите, нажмите CTRL + C в окне терминала, чтобы остановить сервер разработки Flask.

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

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

    Создайте новый файл с помощью предпочитаемого вами текстового редактора и назовите его. Здесь мы назовем файл wsgi.py:

    1. nano ~/myproject/wsgi.py

    В этом файле импортируйте экземпляр Flask из вашего приложения, а затем запустите его:

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

    Сохраните и закройте файл, когда закончите.

    Шаг 4 — Настройка Gunicorn

    Теперь ваше приложение написано с установленной точкой входа, и вы можете приступить к настройке Gunicorn.

    Но сначала перейдите в соответствующий каталог:

    1. cd ~/myproject

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

    Вы также укажете интерфейс и порт для привязки, чтобы приложение запускалось на общедоступном интерфейсе:

    1. gunicorn --bind 0.0.0.0:5000 wsgi:app

    Вы получите следующий вывод:

    Output
    [2021-11-19 23:07:57 +0000] [8760] [INFO] Starting gunicorn 20.1.0 [2021-11-19 23:07:57 +0000] [8760] [INFO] Listening at: http://0.0.0.0:5000 (8760) [2021-11-19 23:07:57 +0000] [8760] [INFO] Using worker: sync [2021-11-19 23:07:57 +0000] [8763] [INFO] Booting worker with pid: 8763 [2021-11-19 23:08:11 +0000] [8760] [INFO] Handling signal: int [2021-11-19 23:08:11 +0000] [8760] [INFO] Shutting down: Master

    Посетите IP-адрес вашего сервера с :5000, добавленным в конце, в веб-браузере еще раз:

    http://your_server_ip:5000
    

    Вывод вашего приложения будет генерировать следующее:

    Убедившись, что он работает правильно, нажмите CTRL + C в окне терминала.

    Поскольку вы закончили работу с виртуальной средой, деактивируйте ее:

    1. deactivate

    Любые команды Python теперь снова будут использовать системную среду Python.

    Затем создайте файл сервисной единицы systemd. Создание файла модуля systemd позволит системе инициализации Ubuntu автоматически запускать Gunicorn и обслуживать приложение Flask при каждой загрузке сервера.

    Создайте юнит-файл, оканчивающийся на .service, в каталоге /etc/systemd/system, чтобы начать:

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

    Внутри начните с раздела [Unit], который используется для указания метаданных и зависимостей. Добавьте здесь описание вашей службы и сообщите системе инициализации, чтобы она запускалась только после достижения цели сети:

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

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

    [Unit]
    Description=Gunicorn instance to serve myproject
    After=network.target
    
    [Service]
    User=sammy
    Group=www-data
    

    Затем наметьте рабочий каталог и установите переменную среды PATH, чтобы система инициализации знала, что исполняемые файлы процесса находятся в вашей виртуальной среде. Также укажите команду для запуска службы. Эта команда сделает следующее:

    • Запустите 3 рабочих процесса (при необходимости вы должны настроить это)
    • Создайте и привяжите файл сокета Unix, myproject.sock, в каталоге вашего проекта.
    • Установите значение umask 007, чтобы файл сокета создавался для предоставления доступа владельцу и группе при ограничении доступа других лиц.
    • Укажите имя файла точки входа WSGI вместе с Python, вызываемым в этом файле (wsgi:app)

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

    Не забудьте заменить имя пользователя и пути проекта своей информацией:

    [Unit]
    Description=Gunicorn instance to serve myproject
    After=network.target
    
    [Service]
    User=sammy
    Group=www-data
    WorkingDirectory=/home/sammy/myproject
    Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
    ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
    

    Наконец, добавьте раздел [Install]. Это сообщит systemd, с чем связать эту службу, если вы включите ее запуск при загрузке. Вы хотите, чтобы эта служба запускалась, когда обычная многопользовательская система запущена и работает:

    [Unit]
    Description=Gunicorn instance to serve myproject
    After=network.target
    
    [Service]
    User=sammy
    Group=www-data
    WorkingDirectory=/home/sammy/myproject
    Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
    ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
    
    [Install]
    WantedBy=multi-user.target
    

    На этом ваш служебный файл systemd готов. Сохраните и закройте его сейчас.

    Теперь запустите созданный вами сервис Gunicorn:

    1. sudo systemctl start myproject

    Затем включите его, чтобы он запускался при загрузке:

    1. sudo systemctl enable myproject

    Проверьте статус:

    1. sudo systemctl status myproject

    Вы должны получить вывод, подобный следующему:

    Output
    ● myproject.service - Gunicorn instance to serve myproject Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset Active: active (running) since Fri 2021-11-19 23:08:44 UTC; 6s ago Main PID: 8770 (gunicorn) Tasks: 4 (limit: 1151) CGroup: /system.slice/myproject.service ├─9291 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─9309 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app ├─9310 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app └─9311 /home/sammy/myproject/myprojectenv/bin/python3.6 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app …

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

    Шаг 5 — Настройка Nginx для прокси-запросов

    Теперь ваш сервер приложений Gunicorn должен быть запущен и работать, ожидая запросов к файлу сокета в каталоге проекта. Затем настройте Nginx для передачи веб-запросов в этот сокет, внеся небольшие дополнения в его файл конфигурации.

    Начните с создания нового файла конфигурации блока сервера в каталоге Nginx sites-available. Мы назовем это myproject, чтобы не противоречить остальной части руководства:

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

    Откройте блок сервера и скажите Nginx прослушивать порт по умолчанию 80. Кроме того, скажите ему использовать этот блок для запросов доменного имени вашего сервера:

    server {
        listen 80;
        server_name your_domain www.your_domain;
    }
    

    Затем добавьте блок местоположения, соответствующий каждому запросу. В этот блок включите файл proxy_params, в котором указаны некоторые общие параметры проксирования, которые необходимо установить. Затем передайте запросы в сокет, который вы определили с помощью директивы proxy_pass:

    server {
        listen 80;
        server_name your_domain www.your_domain;
    
        location / {
            include proxy_params;
            proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
        }
    }
    

    Сохраните и закройте файл, когда закончите.

    Чтобы включить созданную вами конфигурацию блока сервера Nginx, свяжите файл с каталогом sites-enabled. Вы можете сделать это, выполнив команду ln и флаг -s, чтобы создать символическую или мягкую ссылку, а не жесткая ссылка:

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

    С помощью ссылки в этом каталоге вы можете проверить наличие синтаксических ошибок:

    1. sudo nginx -t

    Если это возвращается без каких-либо проблем, перезапустите процесс Nginx, чтобы прочитать новую конфигурацию:

    1. sudo systemctl restart nginx

    Наконец, снова настройте брандмауэр. Поскольку вам больше не нужен доступ через порт 5000, удалите это правило:

    1. sudo ufw delete allow 5000

    Затем разрешите полный доступ к серверу Nginx:

    1. sudo ufw allow 'Nginx Full'

    Теперь вы должны иметь возможность перейти к доменному имени вашего сервера в веб-браузере:

    http://your_domain
    

    Вывод вашего приложения появится в вашем браузере:

    Если вы столкнулись с какими-либо ошибками, попробуйте проверить следующее:

    • sudo less /var/log/nginx/error.log: проверяет журналы ошибок Nginx.
    • sudo less /var/log/nginx/access.log: проверяет журналы доступа Nginx.
    • sudo journalctl -u nginx: проверяет журналы процессов Nginx.
    • sudo journalctl -u myproject: проверяет журналы Gunicorn вашего приложения Flask.

    Шаг 6 — Защита приложения

    Чтобы трафик на ваш сервер оставался безопасным, вы должны получить SSL-сертификат для своего домена. Есть несколько способов сделать это, в том числе получить бесплатный сертификат из Как создать самозаверяющий SSL-сертификат для Nginx в Ubuntu 18.04. Мы пойдем с вариантом один ради целесообразности.

    Сначала установите Certbot с помощью snap:

    1. sudo snap install --classic certbot

    В выводе будет отображаться текущая версия Certbot и указание на успешную установку:

    Output
    certbot 1.21.0 from Certbot Project (certbot-eff✓) installed

    Затем создайте символическую ссылку на только что установленный исполняемый файл /snap/bin/certbot из каталога /usr/bin/. Это обеспечит правильную работу команды certbot на вашем сервере:

    1. sudo ln -s /snap/bin/certbot /usr/bin/certbot

    Certbot предоставляет различные способы получения SSL-сертификатов с помощью подключаемых модулей. Плагин Nginx позаботится о перенастройке Nginx и перезагрузке конфигурации при необходимости. Чтобы использовать этот плагин, введите следующее:

    1. sudo certbot --nginx -d your_domain -d www.your_domain

    Это запускает certbot с плагином --nginx, используя -d, чтобы указать имена, для которых вы хотите, чтобы сертификат был действительным.

    Если вы впервые запускаете certbot, вам будет предложено ввести адрес электронной почты и принять условия обслуживания. После этого certbot свяжется с сервером Let’s Encrypt, чтобы запросить сертификат для вашего домена. В случае успеха вы получите следующий вывод:

    Output
    Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/jeanellehorcasitasphd.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/jeanellehorcasitasphd.com/privkey.pem This certificate expires on 2022-03-03. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. Deploying certificate Successfully deployed certificate foryour_domain to /etc/nginx/sites-enabled/myproject Successfully deployed certificate for your_domain to /etc/nginx/sites-enabled/myproject Congratulations! You have successfully enabled HTTPS on https://your_domain and https://your_domain - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le

    Если вы следовали инструкциям по установке Nginx в предварительных требованиях, вам больше не понадобится избыточный профиль HTTP:

    1. sudo ufw delete allow 'Nginx HTTP'

    Чтобы проверить конфигурацию, снова перейдите в свой домен, используя https://:

    https://your_domain
    

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

    Заключение

    В этом руководстве вы создали и защитили базовое приложение Flask в виртуальной среде Python. Вы создали точку входа WSGI, чтобы любой сервер приложений с поддержкой WSGI мог взаимодействовать с ней, а затем настроили сервер приложений Gunicorn для обеспечения этой функции. После этого вы создали служебный файл systemd для автоматического запуска сервера приложений при загрузке. Вы также создали серверный блок Nginx, который передает трафик веб-клиента на сервер приложений для ретрансляции внешних запросов и защищенного трафика на ваш сервер с помощью Let’s Encrypt.

    Flask — чрезвычайно гибкий фреймворк, предназначенный для предоставления вашим приложениям функциональности, не слишком ограничивая структуру и дизайн. Вы можете использовать общий стек, описанный в этом руководстве, для обслуживания приложений flask, которые вы разрабатываете.