A previous version of this tutorial was written by Kathleen Juell.
Введение
В этом руководстве вы создадите приложение на Python с использованием микрофреймворка Flask на Ubuntu 22.04. Большая часть этого руководства будет посвящена тому, как настроить сервер приложений Gunicorn и как запустить приложение, а также настроить Nginx для работы как обратного прокси-сервера.
Предварительные требования
Прежде чем приступить к этому руководству, у вас должно быть:
-
Сервер с установленной Ubuntu 22.04 и обычным пользователем с правами sudo. Следуйте нашему руководству по начальной настройке сервера для руководства.
-
Установленный Nginx, следуя Шагам 1 и 2 из Как установить Nginx на Ubuntu 22.04.
-
Доменное имя настроено на ваш сервер. Вы можете приобрести его на Namecheap или получить бесплатно на Freenom. Вы можете узнать, как настроить домены на DigitalOcean, следуя соответствующей документации по доменам и DNS. Обязательно создайте следующие записи DNS:
- Запись A с
ваш_домен
, указывающая на общедоступный IP-адрес вашего сервера. - Запись A с
www.ваш_домен
, указывающая на общедоступный IP-адрес вашего сервера.
- Запись A с
-
Знакомство со спецификацией WSGI, которую сервер Gunicorn будет использовать для взаимодействия с вашим приложением Flask. Это обсуждение подробнее рассматривает WSGI.
Шаг 1 — Установка компонентов из репозиториев Ubuntu
Первым шагом будет установка всех необходимых компонентов из репозиториев Ubuntu. Это включает в себя pip
, менеджер пакетов Python, который будет управлять компонентами Python. Вы также получите файлы разработки Python, необходимые для сборки некоторых компонентов Gunicorn.
Сначала обновите локальный индекс пакетов и установите пакеты, которые позволят вам создать ваше рабочее окружение Python. Среди них будут python3-pip
, а также несколько других пакетов и инструментов разработки, необходимых для надежной программной среды:
После установки этих пакетов следующим шагом будет создание виртуальной среды для вашего проекта.
Шаг 2 — Создание виртуальной среды Python
Затем вы настроите виртуальное окружение, чтобы изолировать приложение Flask от других файлов Python на вашей системе.
Начните с установки пакета python3-venv
, который установит модуль venv
:
Затем создайте родительский каталог для вашего проекта Flask. Перейдите в каталог с помощью команды cd
после его создания:
Создайте виртуальное окружение для хранения требований вашего проекта Flask, набрав:
Это установит локальную копию Python и pip
в каталог с именем myprojectenv
внутри вашего каталога проекта.
Перед установкой приложений в виртуальном окружении вам необходимо его активировать. Сделайте это, набрав:
Ваш приглашение изменится, чтобы указать, что теперь вы работаете в виртуальном окружении. Оно будет выглядеть примерно так: (myprojectenv)user@host:~/myproject$
.
Шаг 3 — Настройка приложения Flask
Теперь, когда вы находитесь в виртуальном окружении, вы можете установить Flask и Gunicorn и приступить к разработке вашего приложения.
Сначала установите wheel
с локальным экземпляром pip
, чтобы убедиться, что ваши пакеты установятся, даже если отсутствуют архивы wheel:
Примечание
Независимо от того, какую версию Python вы используете, когда виртуальное окружение активировано, вы должны использовать команду pip
(а не pip3
).
Затем установите Flask и Gunicorn:
Создание примерного приложения
Теперь, когда у вас есть Flask, вы можете создать простое приложение. Flask – это микрофреймворк. В него не включено множество инструментов, которые могли бы быть в более полнофункциональных фреймворках, и он существует в основном как модуль, который вы можете импортировать в свои проекты для помощи в инициализации веб-приложения.
Хотя ваше приложение может быть более сложным, мы создадим наше Flask-приложение в одном файле, называемом myproject.py
:
Код приложения будет находиться в этом файле. Он будет импортировать Flask и создавать объект Flask. Вы можете использовать его, чтобы определить функции, которые должны выполняться, когда запрашивается определенный маршрут:
Это в основном определяет, какой контент отображать при доступе к корневому домену. Сохраните и закройте файл, когда закончите.
Если вы следовали руководству по начальной настройке сервера, у вас должен быть включен брандмауэр UFW. Чтобы протестировать приложение, вам нужно разрешить доступ к порту 5000
:
Теперь вы можете протестировать свое Flask-приложение, набрав:
Вы увидите вывод подобный следующему, включая полезное предупреждение, напоминающее вам не использовать эту настройку сервера в продакшене:
Output* Serving Flask app "myproject" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Посетите IP-адрес вашего сервера, за которым следует :5000
, в вашем веб-браузере:
http://your_server_ip:5000
Вы должны увидеть что-то вроде этого:
Когда закончите, нажмите CTRL-C
в вашем терминальном окне, чтобы остановить сервер разработки Flask.
Создание точки входа WSGI
Затем создайте файл, который будет служить точкой входа для вашего приложения. Это скажет серверу Gunicorn, как взаимодействовать с приложением.
Назовите файл wsgi.py
:
В этом файле импортируйте экземпляр Flask из нашего приложения, а затем запустите его:
Сохраните и закройте файл, когда закончите.
Шаг 4 — Настройка Gunicorn
Теперь ваше приложение написано с установленной точкой входа. Теперь можно перейти к настройке Gunicorn.
Прежде чем продолжить, проверьте, что Gunicorn может правильно обслуживать приложение.
Вы можете сделать это, передав ему имя точки входа приложения. Это формируется как имя модуля (без расширения .py
), плюс имя вызываемой функции внутри приложения. В этом случае это wsgi:app
.
Также укажите интерфейс и порт для привязки с помощью аргумента 0.0.0.0:5000
, чтобы приложение запускалось на общедоступном интерфейсе:
Вы должны увидеть вывод подобный следующему:
Output[2020-05-20 14:13:00 +0000] [46419] [INFO] Starting gunicorn 20.0.4
[2020-05-20 14:13:00 +0000] [46419] [INFO] Listening at: http://0.0.0.0:5000 (46419)
[2020-05-20 14:13:00 +0000] [46419] [INFO] Using worker: sync
[2020-05-20 14:13:00 +0000] [46421] [INFO] Booting worker with pid: 46421
Посетите IP-адрес вашего сервера с добавлением :5000
в конце веб-браузера снова:
http://your_server_ip:5000
Вы должны увидеть вывод вашего приложения:
Когда вы подтвердите, что он работает должным образом, нажмите CTRL-C
в окне терминала.
Когда вы закончите использовать виртуальное окружение, вы можете его деактивировать:
Теперь любые команды Python будут снова использовать системное окружение Python.
Далее создайте файл службы systemd. Создание файла службы systemd позволит инициализационной системе Ubuntu автоматически запускать Gunicorn и обслуживать приложение Flask при каждой загрузке сервера.
Создайте файл юнита, заканчивающийся на .service
внутри каталога /etc/systemd/system
, чтобы начать:
Внутри вы начнете с раздела [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
, в пределах нашего каталога проекта. Мы установим значение маски доступа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 и разрешить ее запуск при загрузке:
Давайте проверим статус:
Вы должны увидеть вывод подобный следующему:
Output● myproject.service - Gunicorn instance to serve myproject
Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-05-10 19:40:41 UTC; 9s ago
Main PID: 17300 (gunicorn)
Tasks: 4 (limit: 2327)
Memory: 56.0M
CPU: 514ms
CGroup: /system.slice/myproject.service
├─17300 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17301 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
├─17302 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
└─17303 /home/sammy/myproject/myprojectenv/bin/python3 /home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
May 10 19:40:41 r systemd[1]: Started Gunicorn instance to serve myproject.
. . .
Если вы видите какие-либо ошибки, обязательно исправьте их, прежде чем продолжить обучение.
Шаг 5 — Настройка Nginx для проксирования запросов
Ваш сервер приложений Gunicorn должен быть запущен и ожидать запросов на сокетном файле в каталоге проекта. Теперь вы можете настроить Nginx для передачи веб-запросов на этот сокет, внесши небольшие изменения в его конфигурационный файл.
Начните с создания нового конфигурационного файла серверного блока в каталоге sites-available
Nginx. Назовите его myproject
, чтобы соответствовать остальной части руководства:
Откройте серверный блок и скажите Nginx слушать порт по умолчанию 80
. Также скажите ему использовать этот блок для запросов к доменному имени нашего сервера:
server {
listen 80;
server_name your_domain www.your_domain;
}
Затем добавьте блок location, который соответствует каждому запросу. В этом блоке вы будете включать файл 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
:
После того как файл находится в этом каталоге, вы можете проверить его на наличие синтаксических ошибок:
Если это возвращается без указания каких-либо проблем, перезапустите процесс Nginx, чтобы прочитать новую конфигурацию:
Наконец, снова настройте брандмауэр. Вам больше не нужен доступ через порт 5000
, поэтому вы можете удалить это правило. Затем вы можете разрешить полный доступ к серверу Nginx:
Теперь вы должны иметь возможность перейти на доменное имя вашего сервера в веб-браузере:
http://your_domain
Вы должны увидеть вывод вашего приложения:
Примечание: Вы получите ошибку HTTP 502 шлюза, если Nginx не сможет получить доступ к сокетному файлу gunicorn. Обычно это происходит из-за того, что домашний каталог пользователя не позволяет другим пользователям получать доступ к файлам внутри него.
Если ваш сокетный файл называется /home/sammy/myproject/myproject.sock
, убедитесь, что /home/sammy
имеет как минимум права 0755
. Вы можете использовать инструмент, такой как chmod
, чтобы изменить права, например, так:
Затем перезагрузите страницу, чтобы увидеть, исчезла ли ошибка HTTP 502.
Если вы столкнетесь с какими-либо ошибками, попробуйте проверить следующее:
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-сертификат для вашего домена. Существует несколько способов сделать это, включая получение бесплатного сертификата от Let’s Encrypt, создание самоподписанного сертификата или покупку у другого провайдера и настройку Nginx для его использования, следуя Шагам с 2 по 6 из Как создать самоподписанный SSL-сертификат для Nginx в Ubuntu 22.04. Мы будем использовать первый вариант (Let’s Encrypt) для экспедиции.
Установите пакет Nginx Certbot с помощью apt
:
Certbot предоставляет различные способы получения SSL-сертификатов через плагины. Плагин Nginx будет заботиться о перенастройке Nginx и перезагрузке конфигурации при необходимости. Чтобы использовать этот плагин, введите следующее:
Это запускает certbot
с плагином --nginx
, используя -d
для указания имен, для которых мы хотели бы, чтобы сертификат был действителен.
Если это ваше первое запуск certbot
, вам будет предложено ввести адрес электронной почты и согласиться с условиями обслуживания. После этого certbot
свяжется с сервером Let’s Encrypt, затем выполнит проверку, чтобы убедиться, что вы контролируете домен, для которого запрашивается сертификат.
Если это проходит успешно, certbot
спросит, как вы хотели бы настроить ваши HTTPS-настройки:
OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
Выберите свой вариант, затем нажмите ENTER
. Конфигурация будет обновлена, и Nginx перезагрузится, чтобы применить новые настройки. certbot
завершит процесс сообщением о том, что он прошел успешно, и укажет местоположение ваших сертификатов:
OutputIMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your_domain/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/your_domain/privkey.pem
Your cert will expire on 2020-08-18. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- 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:
Для проверки конфигурации снова перейдите на ваш домен, используя https://
:
https://your_domain
Вы должны увидеть вывод вашего приложения снова, вместе с индикатором безопасности вашего браузера, который должен указывать, что сайт защищен.
Заключение
В этом руководстве вы создали и обеспечили безопасность простого приложения Flask виртуальной средой Python. Вы создали точку входа WSGI, чтобы любой сервер приложений, поддерживающий WSGI, мог взаимодействовать с ним, а затем настроили сервер приложений Gunicorn для обеспечения этой функции. После этого вы создали файл службы systemd для автоматического запуска сервера приложений при загрузке. Вы также создали блок сервера Nginx, который направляет трафик веб-клиента на сервер приложений, перенаправляя внешние запросы, и обеспечили безопасность трафика к вашему серверу с помощью Let’s Encrypt.
Flask – это очень простой, но крайне гибкий фреймворк, предназначенный для предоставления вашим приложениям функциональности, не ограничивая слишком сильно их структуру и дизайн. Вы можете использовать общий стек, описанный в этом руководстве, чтобы обслуживать созданные вами приложения Flask.