Материал посвящен использованию Flask в Ubuntu. В рамках статьи рассмотрим основы функционирования Gunicorn и Nginx для развертывания прокси под Frontend.
Нам понадобится хост с предустановленной Ubuntu. Желательно создать на сервере обычного пользователя с правами sudo
. Например, арендуйте готовую к эксплуатации удаленную машину у провайдера Timeweb Cloud.
Также понадобится:
your_domain
.www
.Желательно иметь представление о спецификации WSGI. Это поможет понять, как Gunicorn обменивается данными и командами с приложениями Flask.
cloud
В рамках подготовки к работе постановим менеджер pip
, с его помощью мы будем манипулировать компонентами Python. Плюс скачаем файлы, требуемые для создания ряда элементов Gunicorn. Но предварительно скачаем обновления пакетов и установим python3-pip
, он нужен для организации среды разработки:
sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
Виртуальные окружения позволяют разделять зависимости приложений, размещенных на одном сервере. Первый этап:
sudo apt install python3-venv
Вторым этапом сделаем родительскую директорию, где будем хранить весь проект Flask. И сразу перейдем в нее:
mkdir ~/myproject
cd ~/myproject
Третьим этапом организуем непосредственно виртуальную среду Python:
python3 -m venv myprojectenv
Все используемые впоследствии файлы будут сохраняться в папке myprojectenv
. Остается провести активацию:
source myprojectenv/bin/activate
Результат будет заметен по изменившемуся виду командной строки. Она примет такой вид:
(myprojectenv)user@host:~/myproject$
Обновим pip
:
pip install -U pip
Следом загрузим Flask и Gunicorn:
pip install gunicorn flask
Теперь применим Flask для создания простейшей программы. Но важно учитывать, что данную микроструктуру чаще берут в качестве дополнительного модуля, т.к. в ней минимум инструментов из тех, что обычно актуальны при веб-разработке. В качестве примера создадим простой вариант под названием myproject.py
:
nano ~/myproject/myproject.py
В указанный файл мы сохраним код программы. При запуске будет импортирован Flask и создан экземпляр объекта. Например, вот так:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h >Hello!<h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
После внесения изменений закройте файл с сохранением. Теперь проверим работоспособность кода, но сначала настроим брандмауэр, чтобы тот разрешал трафик по порту 5000.
sudo ufw allow 5000
Теперь система готова к тесту программного модуля Flask:
python myproject.py
Теперь откроем наш домен по IP с указанием порта:
http://your_server_ip:5000
В окне браузера увидим «Hello!». Завершим сессию и отключим сервер нажатием комбинации <Ctrl+C> (в терминале).
Переходим к созданию файла, который послужит нам точкой входа в разрабатываемую программу. Он «подскажет» серверу Gunicorn, каким образом обмениваться данными с ним.
nano ~/myproject/wsgi.py
Перенесем экземпляр Flask в только что созданный файл, после чего откроем его:
from myproject import app
if __name__ == "__main__":
app.run()
По итогу закроем его.
Перед продолжением работы убедимся, что сервер Gunicorn способен правильно обрабатывать нашу программу. Выполняется это передачей наименования точки входа без расширения и имени вызываемого элемента. Возьмем, например, wsgi:app
. Еще в команде понадобится указать номер порта с интерфейсом:
cd ~/myproject
gunicorn --bind 0.0.0.0:5000 wsgi:app
Перейдем в браузер и введем IP нашего сервера с портом под номером 5000:
http://your_server_ip:5000
Программа выдаст сообщение «Hello!». Завершим работу нажатием кнопок <Ctrl + C> в окне терминала. И отключим виртуальную среду:
deactivate
После этого все команды Python будут иметь отношение только к общей системной среде. Если работать с виртуальной придется постоянно, есть смысл запускать ее автоматически вместе с операционкой. С этой целью сгенерируем файл автозагрузки. Сначала создадим *.service
и разместим в папке /etc/systemd/system
:
sudo nano /etc/systemd/system/myproject.service
Первоначально [Unit]
, куда обычно вносят метаданные и зависимости, внесем описание службы и зададим условие инициализировать «виртуалку» после подтверждения наличия связи:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
В блоке [Service]
укажем аккаунт и группу, от имени которых будет запускаться процесс.
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=username
Group=www-data
Следующим шагом укажем переменную PATH
, чтобы при активизации система сразу «понимала», где брать требуемые файлы (в «виртуалке»).
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=username
Group=www-data
WorkingDirectory=/home/username/myproject
Environment="PATH=/home/username/myproject/myprojectenv/bin"
ExecStart=/home/username/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
Следует учитывать, что для systemd
нужно указывать полный путь к файлу Gunicorn, размещенному в «виртуалке».
В итоге добавим раздел [Install]
и внесем в него:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=username
Group=www-data
WorkingDirectory=/home/username/myproject
Environment="PATH=/home/username/myproject/myprojectenv/bin"
ExecStart=/home/username/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
Все, файл systemd
подготовлен. Закройте его с сохранением изменений. И можно запускать службу Guricorn (сразу настроим ее загрузку вместе с операционкой):
sudo systemctl start myproject
sudo systemctl enable myproject
Остается проверить ее текущее состояние:
sudo systemctl status myproject
Переходим к работе с веб-сервером Nginx (Gunicorn не используется в качестве фронтенд-сервера, и обычно настраивается реверс-прокси. В нашем случае это будет Nginx). Сначала создадим файл с конфигурацией в директории с sites-available
, назовем его myproject
.
sudo nano /etc/nginx/sites-available/myproject
В нем укажем веб-серверу прослушивать порт 80 и использовать серверный блок при всех запросах нашего домена:
server {
listen 80;
server_name your_domain www.your_domain;
}
Следом добавим location
, где укажем proxy_params
, определяющий параметры настраиваемого прокси.
server {
listen 80;
server_name your_domain www.your_domain;
location / {
include proxy_params;
proxy_pass http://unix:/home/username/myproject/myproject.sock;
}
}
Закроем файл с сохранением изменений. И применим новую конфигурацию путем привязки к директории sites-enabled
.
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Также добавим пользователя www-data
в группу текущего пользователя. Для этого выполним:
sudo usermod -a -G ${USER} www-data
Проверим конфигурацию Nginx:
sudo nginx -t
И если все в порядке, перезапустим его:
sudo nginx -s reload
Завершим настройку внесением изменений в параметры брандмауэра. Например, правило насчет доступа через порт 5000 нам уже не понадобится, его можно смело удалять. Вместо него внесем другой, для открытия подключения к серверу Nginx:
sudo ufw delete allow 5000
sudo ufw allow 'Nginx Full'
Попробуйте зайти на наш сервер из браузера: http://your_domain
. Программа выдаст сообщение «Hello!»
Последняя задача в этом материале – установка SSL сертификата для защиты трафика. Мы рекомендуем получить бесплатный SSL Let’s Encrypt с помощью Certbot. Рекомендуемый способ установки Certbot — через snap
, который уже предустановлен в Ubuntu.
Подробную инструкцию по выпуску SSL можно найти в официальной документации Certbot.
Выполните команду ниже, чтобы убедиться, что используется последняя версия snapd
:
sudo snap install core; sudo snap refresh core
Если ранее вы устанавливали какие-то пакеты Certbot с помощью пакетного менеджера apt
, удалите их командой:
sudo apt-get remove certbot
Установите Certbot через snap
:
sudo snap install --classic certbot
Выполните следующее, чтобы убедиться, что команда certbot
может быть запущена:
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Выполните команду ниже, чтобы получить сертификат и автоматически внести необходимые изменений в конфигурацию Nginx:
sudo certbot --nginx
Certbot будет автоматически обновлять сертификат. Вы можете протестировать обновление, запустив команду:
sudo certbot renew --dry-run
После проверьте открытие домена https://your_domain
в браузере. Помимо традиционного результата в виде сообщения «Hello!», должен появиться замочек, подтверждающий защиту сайта.
Подготовили для вас выгодные тарифы на облачные серверы
Вот мы и разобрались, как работать в микрофреймворке Flask на сервере Ubuntu с применением виртуальной среды Python. Система довольно гибкая, свободно обеспечивает работу приложений практически без структурных ограничений.
Здраствуйте. Столкнулся с проблемой исчезновения файла myproject.sock после выполнения команды:
Поддержка тактично «послала», возможно тут подскажете в чем может быть причина.
Или, возможно кто-то сталкивался с аналогичной проблемой и смог ее решить...
Все сделано 1:1 как в статье
Вообще было бы неплохо добавить описание решение возможных проблем в статье.
Добрый день! Сходу не удалось определить, в чем может быть проблема, ошибок в статье не нашли. Можете сообщить номер тикета? Попробуем разобраться.
Тикет №8804094 и Тикет №8923593 Только я уверен что это не решит проблемы, поскольку меня уже отфутболили, дважды!
Добрый день! Коллеги подготовили 2 способа, которые возможно помогут решить вашу проблему.
Важная информация!
Поднимать сервис необходимо не через root-пользователя. Нужно создать нового пользователя и поднимать проект в его домашней директории /home/user. Также, устанавливаем следующие права на файлы:
1 способ. Удаление файла myproject.sock
Количество workers равно количеству ядер на сервере.
Добавляем в файл /etc/systemd/system/myproject.service следующую строку, которая удаляет myproject.sock перед запуском сервиса:
ExecStartPre=/bin/rm -f /home/username/myproject/myproject.sock
После этого обновляем файл. А после перезагружаем процесс systemd:2 способ. Переход с unix-сокета на TCP-сокет
Меняем строку ExecStart на следующую:
ExecStart=/home/username/myproject/myprojectenv/bin/gunicorn -- workers 3 --bind 0.0.0.0:5000 wsgi:app
Unix socket заменяется на 0.0.0.0:5000. А так выглядит конфигурация Nginx: Примечание: везде замените username на имя пользователя!Проделал все шаги.
Через 5000 порт при ручном запуске с активированной виртуалкой все работает.
Запустить работу через домен не удалось. Вместе с поддержкой TimeWeb Cloud бились пол-дня и имеем:
502 Bad Gateway
Вот что написала поддержка:
Можете подсказать как решить проблему?
Нашел решение в статье про Django: для решения проблемы нужно добавить пользователя www-data в группу текущего пользователя:
Добавьте куда-нибудь в статью, наверное )
Добавили 💙
Добрый день!
Начинаете с User=username (пятая строка в примере кода):
В блоке [Service] укажем аккаунт и группу, от имени которых будет запускаться процесс.
А затем продолжаете с User=user:
Следует учитывать, что для systemd нужно указывать полный путь к файлу Gunicorn, размещенному в «виртуалке».
В итоге добавим раздел [install] и внесем в него:
Наверное где-то неправильно, или так и нужно?
Добрый день! Да, это ошибка, везде должен быть один и тот же пользователь. Спасибо, что сообщили 💙 Мы исправили в статье.
Немного недоисправляли:
7, 8, 9 строчки тоже нужно user заменить на username
Действительно. Спасибо :)
здравствуйте! проблемка, сайт поднялся но на публичном ip ничего, что делать?
Добрый день! В статье мы описывали размещение сайта на домене, но если вы хотите, чтобы сайт был доступен по публичному IP сервера, попробуйте указать в конфигурации Nginx
listen ip_адрес_сервера:80
вместоlisten 80
:После чего перезапустите Nginx: