Запуск приложения на Flask с помощью uwsgi + nginx в Debian 7
Данная статья описывает настройку связки uwsgi и nginx для обслуживания сайта созданного с применением фреймворка Flask. При этом статья писалась для вполне конкретной ситуации: Установка Flask и Python 3.3 в Debian 7. То есть в Debian 7.2 мы имеем вручную установленный из исходников python 3.3, на основе которого создано виртуальное окружение.
Приложение на Flask
В качестве тестового приложения будем использовать код из руководства по Flask:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
Установка и настройка Nginx
Начнем с nginx, так как его настройка оказалась тривиальной. Устанавливаем:
aptitude install nginx
Создаем конфиг:
nano /etc/nginx/sites-available/site
Со следующим содержимым:
server {
listen 80;
server_name domain.tld;
location / { try_files $uri @app; }
location @app {
uwsgi_pass 127.0.0.1:4242;
include uwsgi_params;
}
}
Где domain.tld - доменное имя сайта, app - имя вашего приложения в файле с кодом на Flask, 127.0.0.1:4242 - адрес и порт на котором слушает uwsgi. Можно также настроить на общение через сокет, но в интернете есть информация, что с данным способом могут быть некоторые проблемы.
Затем линкуем его в директорию /etc/nginx/sites-enabled:
ln -s /etc/nginx/sites-available/dev /etc/nginx/sites-enabled/
И перезапускаем nginx:
/etc/init.d/nginx restart
Установка и настройка uwsgi
Устанавливаем uwsgi в уже настроенное виртуальное окружение:
cd /var/www/dev/ . venv/bin/activate pip install uwsgi
После этого долго не удавалось запустить uwsgi так, чтобы он увидел приложение. Путем нескольких часов экспериментов был подобран конфиг. Создаем конфигурационный файл:
nano /var/www/dev/site.ini
В который пишем:
[uwsgi]
gid = www-data
uid = www-data
socket=127.0.0.1:4242
pidfile=/var/run/uwsgi
virtualenv=/var/www/dev/venv/
chdir=/var/www/dev/
module=site
callable=app
pythonpath=/var/www/dev/venv/lib/python3.3/site-packages/
no-site=True
touch-reload=/var/www/dev/site.py
master = true
processes = 1
threads = 10
enable-threads = True
log-syslog = uwsgi-ligo
Где uid и gid задают пользователя и группу от которых будет работать uwsgi. В socket задаем адрес и порт, в virtualenv путь до директории в которой содержится виртуальное окружение, с помощью pidfile задаем путь до файла с номером процесса, параметр chdir указывает путь до директории с кодом сайта, module - название модуля, то есть имя файла в котором содержится приложение без .py. Далее в callable указываем вызываемое приложение взятое из строки app = Flask(__name__).
pythonpath позволяет задать набор директорий в которых искать модули python. Таких строк может быть до 64. Определить данный путь удалось экспериментальным путем, он ведет в директорию, в которой установлен Flask. Путь начинается с пути до виртуального окружения, так как Flask был установлен конкретно в этом окружении.
no-site - данный параметр мешал нормальной работе в данной ситуации, как написано в официальной справке: если сомневаетесь, то лучше выключить. touch-reload - сообщает uwsgi перезапускаться в случае изменения указанного файла. Если задать значение master, то будет запущен один главный процесс, под которым будут запущены остальные, в количестве указанном в параметре processes. Параметр threads задает количество процессов, которые может запустить процесс. enable-threads - просто включаем поддержку процессов. log-syslog - здесь задаем имя под которым будут писаться логи в syslog.
Теперь запускаем uwsgi:
/var/www/dev/venv/bin/uwsgi --ini /var/www/dev/site.ini
И получаем ошибки в виде traceback о том, что не хватает такого-то модуля python. Проблема связана с тем, что при создании виртуального окружения не все модули линкуются в виртуальное окружение. То есть модули в виртуальном окружении являются символическими ссылками на модули в основной директории python. Останавливаем uwsgi с помощью Ctrl+C и линкуем все модули в виртуальное окружение:
cd /opt/python3.3/lib/python3.3 ls -l | awk '{print "/opt/python3.3/lib/python3.3/"$NF}' | xargs ln -s -f -t /var/www/dev/venv/lib/python3.3/
Вторая и третья строки - одна строка. Проверьте, что символические ссылки создались нормально.
Теперь можно запустить uwsgi в фоне:
/var/www/dev/venv/bin/uwsgi --ini /var/www/dev/site.ini &
На экране информацию о запуске вы не увидите, ее можно почерпнуть из лога /var/log/syslog. Нормальный вывод выглядит примерно так:
*** Starting uWSGI 1.9.19 (64bit) on [Fri Nov 15 18:48:55 2013] ***
compiled with version: 4.7.2 on 15 November 2013 01:35:20
os: Linux-3.2.0-4-amd64 #1 SMP Debian 3.2.51-1
nodename: VPS
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 4
current working directory: /var/www/dev
detected binary path: /var/www/dev/venv/bin/uwsgi
setgid() to 33
setuid() to 33
your processes number limit is 47806
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 127.0.0.1:4242 fd 7
Python version: 3.3.2 (default, Nov 6 2013, 19:45:44) [GCC 4.7.2]
Set PythonHome to /var/www/dev/venv/
Python main interpreter initialized at 0x2201150
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 331648 bytes (323 KB) for 10 cores
*** Operational MODE: threaded ***
added /var/www/dev/venv/lib/python3.3/site-packages/ to pythonpath.
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x2201150 pid: 24919 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 24919)
spawned uWSGI worker 1 (pid: 24922, cores: 10)
Чтобы перезапустить uwsgi достаточно изменить файл /var/www/dev/site.py или "прикоснуться" к нему:
touch /var/www/dev/site.py
Напрямую можно перезапустить послав сигнал HUP в master-процесс:
kill -HUP `cat /var/run/uwsgi`
Теперь остается сделать так, чтобы uwsgi мог запускаться вместе со стартом системы. Для этого используем supervisord.
Установка и настройка supervisord
Установка, как обычно:
aptitude install supervisor
Теперь создаем конфигурационный файл:
nano /etc/supervisor/conf.d/site.conf
со следующим содержимым:
[program:dev]
directory=/var/www/dev
command=/var/www/dev/venv/bin/uwsgi --ini /var/www/dev/site.ini
user=root
autostart=true
autorestart=true
stdout_logfile=/var/log/uwsgi.log
stderr_logfile = /var/log/uwsgi_err.log
redirect_stderr=true
stopsignal=INT
Dev в первой строке - это просто идентификатор, с помощью которого можно будет производить действия над заданной командой. directory - путь до директории в которой работает проект, command - собственно команда для запуска uwsgi.
user - в этой директиве пришлось указать root, иначе uwsgi не запускался.
Теперь запускать, останавливать или перезапускать uwsgi можно с помощью команд для supervisord. К примеру:
/etc/init.d/supervisord start
Также отдельными командами можно управлять с помощью supervisorctl:
# supervisorctl
dev RUNNING pid 615, uptime 0:00:12
supervisor> help
default commands (type help <topic>):
=====================================
add clear fg open quit remove restart start stop update
avail exit maintail pid reload reread shutdown status tail version
При использовании команды supervisorctl откроется отдельная консоль с ограниченным набором команд. Справку по команде можно получить с помощью help, к примеру, help update.
В общем-то и все.
Опубликовано