Доброго времени суток, хабровчане!
Появилось свободное время, и возникло желание сделать небольшую веб-приложение. Идея есть (получать данные с метеодатчика, хранить в БД и потом делать что-то интересное), свободный сервер на centos тоже. Туториалов по настройке вроде бы тоже… Но на момент написания ни одного полностью рабочего не нашлось. Если вы тоже хотите развернуть приложение на сервере CentOS 7.4 используя связку python3.*, uwsgi и nginx, добро пожаловать под кат.
Итак, что уже должно быть и что не будет освещаться в этой статье:
Первым делом после подключения root-пользователем следует создать нового пользователя с правами администратора (это не обязательно, но как минимум хороший тон):
Здесь потребуется ввести и подтвердить пароль пользователя
Добавляем пользователя в группу локальных администраторов
Переключаемся на свежесозданного пользователя.
Теперь готовим окружение:
Хотелось бы обратить внимание на предпоследнюю строчку — «Development Tools» и «Development Libraries» необходимы для корректного запуска виртуальной среды. Флаг -у используем чтобы команда отрабатывала без запроса подтверждения.
Теперь можно приступать к созданию рабочей директории:
Теперь подготовим точку входа в веб-приложение:
Это код после запуска позволит нам убедиться, что все предпринятые ранее шаги прошли успешно. Для тестирования запустим сервис:
При физическом ljcnegt или rdp-подключении результат можно проверить в браузере по адресу 0.0.0.0:8080. При SSH-подключении откроем новую сессию и протестируем с помощью curl:
Флаг -v позволит увидеть полный вывод.
После завершения тестирования стоит завершить работу сервиса нажав CTRL+C (иначе придётся искать процесс и убивать его с помощью kill. Тоже выход, но определённо менее удобный).
Теперь можно сделать основное веб-приложение:
Процесс тестирования довольно похож на предыдущий — запускаем приложение с помощью команды
Теперь отредактируем точку входа так, чтобы при её вызове запускалось наше приложение:
Теперь самое сложное и интересное. Пора делать из этого приложения сервис, который будет работать автоматически и в фоновом режиме.
Для начала подготовим ini-файл для uwsgi:
Здесь хочется обратить внимание на следующие строчки:
Теперь можно приступать непосредственно к созданию сервиса:
Все интересные строчки находятся в блоке Service:
Теперь запустим сервис:
Последняя команда сделает его автозапускающимся после перезагрузки сервера.
И последний рывок — настроим сервер nginx и сделаем наше веб-приложение доступным для внешней сети. Лог его работы всегда можно посмотреть с помощью команды
Найдём блок [Service] и в конце добавим PrivateTmp=false.
После этого перезагрузим демонов командой
Теперь приступим непосредственно к конфигурации сервера:
Находим блок http и добавляем новый сервер:
Теперь осталось включить сервер и отредактировать правила на фаерволе:
Теперь при обращении к серверу по его доменному имени или IP-адресу мы будем получать ответ от нашего приложения на Flask.
Надеюсь, данный материал окажется полезным.
Появилось свободное время, и возникло желание сделать небольшую веб-приложение. Идея есть (получать данные с метеодатчика, хранить в БД и потом делать что-то интересное), свободный сервер на centos тоже. Туториалов по настройке вроде бы тоже… Но на момент написания ни одного полностью рабочего не нашлось. Если вы тоже хотите развернуть приложение на сервере CentOS 7.4 используя связку python3.*, uwsgi и nginx, добро пожаловать под кат.
Итак, что уже должно быть и что не будет освещаться в этой статье:
- Физический или виртуальный сервер с ОС CentOS 7.4 (для других ОС и версий работоспособность не гарантируется).
- Доступ к серверу с правами суперпользователя *если сервер виртуальный, то предполагается, что есть возможность и умение подключиться к нему по SSH).
Первым делом после подключения root-пользователем следует создать нового пользователя с правами администратора (это не обязательно, но как минимум хороший тон):
adduser developer
passwd developer
Здесь потребуется ввести и подтвердить пароль пользователя
usermod -aG wheel developer
Добавляем пользователя в группу локальных администраторов
su - developer
Переключаемся на свежесозданного пользователя.
Теперь готовим окружение:
sudo yum install -y epel-release
sudo yum install -y python3 python3-pip python3-devel nginx gcc
sudo yum update -y python36 python2
sudo yum groupinstall -y "Development Tools" "Development Libraries"
sudo yum install -y python3-devel python36-virtualenv
Хотелось бы обратить внимание на предпоследнюю строчку — «Development Tools» и «Development Libraries» необходимы для корректного запуска виртуальной среды. Флаг -у используем чтобы команда отрабатывала без запроса подтверждения.
Теперь можно приступать к созданию рабочей директории:
sudo mkdir /opt/myproject && cd /opt/myproject
sudo chown -R developer /opt/
python3 -m venv myprojectenv
source myprojectenv/bin/activate
pip3 install --upgrade pip
pip3 install uwsgi flask
Теперь подготовим точку входа в веб-приложение:
vi /opt/myproject/wsgi.py
(здесь и далее я буду использовать редактор vi, однако это дело вкуса)def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ["<h1 style='color:blue'>Testing Success!</h1>"]
Это код после запуска позволит нам убедиться, что все предпринятые ранее шаги прошли успешно. Для тестирования запустим сервис:
uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi
При физическом ljcnegt или rdp-подключении результат можно проверить в браузере по адресу 0.0.0.0:8080. При SSH-подключении откроем новую сессию и протестируем с помощью curl:
curl -v 0.0.0.0:8080
Флаг -v позволит увидеть полный вывод.
После завершения тестирования стоит завершить работу сервиса нажав CTRL+C (иначе придётся искать процесс и убивать его с помощью kill. Тоже выход, но определённо менее удобный).
Теперь можно сделать основное веб-приложение:
vi /opt/myproject/myproject.py
from flask import Flask
application = Flask(__name__)
@application.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
application.run(host='0.0.0.0')
Процесс тестирования довольно похож на предыдущий — запускаем приложение с помощью команды
python3 /opt/myproject/myproject.py
и проверяем. результат должен быть одинаков.Теперь отредактируем точку входа так, чтобы при её вызове запускалось наше приложение:
vi /opt/myproject/wsgi.py
from myproject import application
if __name__ == "__main__":
application.run()
Теперь самое сложное и интересное. Пора делать из этого приложения сервис, который будет работать автоматически и в фоновом режиме.
Для начала подготовим ini-файл для uwsgi:
vi /opt/myproject/myproject.ini
[uwsgi]
wsgi-file = myproject/wsgi.py
master = true
processes = 2
uid = developer
socket = /tmp/uwsgi/myproject.sock
chown-socket = nginx:nginx
chmod-socket = 666
vacuum = true
die-on-term = true
Здесь хочется обратить внимание на следующие строчки:
- socket = /tmp/uwsgi/myproject.sock — для ускорения работы сервиса стоит использовать unix-socket, а для того, чтобы к нему смог подключиться nginx — создать его во временной папке /tmp/uwsgi
- chown-socket = nginx:nginx передаст права на использование сокета пользователю nginx
- chmod-socket = 666 — служит для тех же целей, что и предыдущая. В разных руководствах и советах фигурируют разные значения параметра — 664, 665, 777 — но опытным путём установлено, что 666 — минимально рабочий.
Теперь можно приступать непосредственно к созданию сервиса:
sudo vi /etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject app
After=network.target
[Service]
ExecStartPre=-/usr/bin/bash -c 'mkdir -p /tmp/uwsgi chown nginx:nginx /tmp/uwsgi'
ExecStart=/usr/bin/bash -c 'cd /opt/myproject; source myprojectenv/bin/activate; uwsgi --ini myproject.ini'
ExecStartPost=/usr/bin/bash -c 'setenforce 0'
PrivateTmp=false
[Install]
WantedBy=multi-user.target
Все интересные строчки находятся в блоке Service:
- ExecStartPre — это команда, которую менеджер системы выполнит перед запуском сервиса.
-/usr/bin/bash -c объявляет запуск последующей последовательности команд, а 'mkdir -p /tmp/uwsgi chown nginx:nginx /tmp/uwsgi' создаст временную папку для сокета и передаст права пользователю nginx. - ExecStart — команда, непосредственно запускающая сервис, и в ней мы последовательно перйдём в рабочую директорию, активируем виртуальную среду и запустим uwsgi-сервер из ini файла.
- ExecStartPost — команда, которая выполняется после запуска сервиса. В нашем случае она требуется для корректной передачи запросов от сервера nginx к uwsgi-серверу.
- PrivateTmp=false — это параметр, который делает созданную временную папку видимой для остальных процессов.
Теперь запустим сервис:
systemctl start myproject
systemctl status myproject
systemctl enable myproject
Последняя команда сделает его автозапускающимся после перезагрузки сервера.
И последний рывок — настроим сервер nginx и сделаем наше веб-приложение доступным для внешней сети. Лог его работы всегда можно посмотреть с помощью команды
journalctl -u myproject
sudo vi /usr/lib/systemd/system/nginx.service
Найдём блок [Service] и в конце добавим PrivateTmp=false.
После этого перезагрузим демонов командой
systemctl daemon-reload
Теперь приступим непосредственно к конфигурации сервера:
vi /etc/nginx/nginx.conf
http {
. . .
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
. . .
Находим блок http и добавляем новый сервер:
server {
listen 80;
server_name server_domain_or_IP;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi/myproject.sock;
}
}
Теперь осталось включить сервер и отредактировать правила на фаерволе:
systemctl start nginx
systemctl enable nginx
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --reload
Теперь при обращении к серверу по его доменному имени или IP-адресу мы будем получать ответ от нашего приложения на Flask.
Надеюсь, данный материал окажется полезным.