Как стать автором
Обновить

Nginx + uWSGI + virtualenv + Django на Debian Squeeze

Django *
Некоторое время назад озадачился поиском способа развертывания проектов Django, к которому предъявлялись два требования:
  1. Удобное управление запуском/остановкой/перезапуском нескольких проектов на одном хосте
  2. Поддержка разных виртуальных сред для разных проектов

По второму пункту мой выбор склонился в пользу Nginx + uWSGI. По первому же, из рассмотренных мною вариантов больше всего понравились обвязки для uWSGI в Debian.

Установка ПО


Поддержка uWSGI появилась в Nginx с версии 0.8.40, но ни первого, ни второго в стабильной ветке Debian нет. Поэтому Nginx будем брать из бэкпортов, а uWSGI – из нестабильной ветки. Для этого добавим следующие строчки в /etc/apt/sources.list:
deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
deb http://ftp.ru.debian.org/debian testing main non-free contrib
deb http://ftp.ru.debian.org/debian unstable main non-free contrib

И создадим примерно такой /etc/apt/preferences:
Package: *
Pin: release a=stable
Pin-Priority: 700

Package: *
Pin: release a=squeeze-backports
Pin-Priority: 675

Package: *
Pin: release a=testing
Pin-Priority: 650

Package: *
Pin: release a=unstable
Pin-Priority: 600 

Синхронизируемся с помощью aptitude update и устанавливаем необходимые пакеты:
aptitude -t squeeze-backports install nginx
aptitude -t unstable install uwsgi
aptitude -t unstable install uwsgi-plugin-python
aptitude -t unstable install python-virtualenv

Структура каталогов для проектов


Рассмотрим развертывание для проекта example. Для определенности, предположим, что все проекты размещаются в подкаталоге proj домашнего каталога пользователя web. Так же в proj имеется подкаталог static, где будут размещаться статические файлы проектов, за раздачу которых будет отвечать Nginx. Для проекта example получим следующие пути:
/home/web/proj/example
/home/web/proj/static/example

В settings.py проекта example имеем настройки:
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '../static/example'))
STATIC_URL = '/static/' 

Таким образом менеджмент-команда collectstatic будет собирать всю статику проекта в /home/web/proj/static/example.

Виртуальное окружение для проекта example будет находиться в /home/web/envs/example.

Настройка uWSGI и Nginx


Конфигурационный файл uWSGI для проекта example будет называться /etc/uwsgi/apps-available/example.ini и примет следующий вид:
[uwsgi]
	plugins = python27
	virtualenv = /home/web/envs/example/
	chdir = /home/web/proj/example/
	pythonpath = ..
	env = DJANGO_SETTINGS_MODULE=example.settings
	module = django.core.handlers.wsgi:WSGIHandler()
	touch-reload = /home/web/proj/example/touchme 

Также создаем символическую ссылку на него в /etc/uwsgi/apps-enabled:
cd /etc/uwsgi/apps-enabled
ln -s ../apps-available/example.ini .

После чего запускаем демон uWSGI: /etc/init.d/uwsgi start example

Конфигурационный файл Nginx назовем /etc/nginx/sites-available/example. Его минимальный вариант может быть таким:
server {
	listen	80;

	server_name	example;

	access_log	/var/log/nginx/example.access.log;
	error_log	/var/log/nginx/example.error.log;

	location /static/ {
		alias	/home/web/proj/static/example/;
	}

	location / {
		include	uwsgi_params;
		uwsgi_pass	unix:///var/run/uwsgi/app/example/socket;
	}
}

Точно так же создаем символическую ссылку в /etc/nginx/sites-enabled:
cd /etc/nginx/sites-enabled/
ln -s ../sites-available/example .

И перезапускаем Nginx: /etc/init.d/nginx restart

Под капотом


Сначала вкратце остановлюсь на пераметрах в конфигурационном файле uWSGI. Параметр plugins явно задает версию Python. Параметры chdir и pythonpath добавляют каталог проекта и его родительский каталог в пути поиска Python. Параметры env и module позволяют обойтись без создания специального скрипта для запуска проекта демоном uWSGI. Параметр touch-reload позволяет делать перезагрузку проекта с помощью команды touch /home/web/proj/example/touchme.

Такой лаконичный файл конфигурации для uWSGI получился потому, что стартовый скрипт /etc/init.d/uwsgi использует еще один конфигурационный файл /usr/share/uwsgi/conf/default.ini, в котором для всех остальных необходимых параметров заданы достаточно разумные значения по умолчанию. При необходимости их можно переопределить в /etc/uwsgi/apps-available/example.ini. За удалением некоторых комментариев, содержимое /usr/share/uwsgi/conf/default.ini будет следующим:
[uwsgi]
# try to autoload appropriate plugin if "unknown" option has been specified
autoload = true

# enable master process manager
master = true

# spawn 2 uWSGI worker processes
workers = 2

# automatically kill workers on master's death
no-orphans = true

# write master's pid in file /run/uwsgi/<confnamespace>/<confname>/pid
pidfile = /run/uwsgi/%(deb-confnamespace)/%n/pid

# bind to UNIX socket at /run/uwsgi/<confnamespace>/<confname>/socket
socket = /run/uwsgi/%(deb-confnamespace)/%n/socket

# set mode of created UNIX socket
chmod-socket = 660

# place timestamps into log
log-date = true

# user identifier of uWSGI processes
uid = www-data

# group identifier of uWSGI processes
gid = www-data

В обвязках к uWSGI в Debian введено понятие конфигурационного пространства имен. В default.ini оно представлено с помощью переменной %(deb-confnamespace) со значением по умолчанию app. Имя конфигурационного пространства имен определяется следующим образом: стартовый скрипт /etc/init.d/uwsgi ищет в каталоге /etc/uwsgi все подкаталоги, заканчивающиеся на s-enabled, и часть имени подкаталога, предшествующая s-enabled становится именем конфигурационного пространства для файлов в этом подкаталоге. В нашем случае можно было бы создать в /etc/uwsgi более привычные подкаталоги sites-available и sites-enabled, в которые поместить файл конфигурации example.ini и символическую ссылку на него соответственно; pidfile и socket для этой конфигурации находились бы в /run/uwsgi/site/example/pid и /run/uwsgi/site/example/socket, а управление демоном uWSGI для этой конфигурации осуществлялось бы с помощью команд /etc/init.d/uwsgi start|stop|restart site/example. При отсутствии префикса подразумевается пространство имен app.
Теги:
Хабы:
Всего голосов 28: ↑25 и ↓3 +22
Просмотры 33K
Комментарии Комментарии 45