http://habrahabr.ru/post/226419/
Перед вами руководство по настройке production окружения для Django. Здесь будут описаны необходимые шаги по настройке Django, uWSGI и nginx. Руководство охватывает все три компонента — полный стек серверного ПО для веб-приложений.
Подразумевается, что вы используете Unix-подобную операционную систему и менеджер пакетов, эквивалентный aptitude. Найти эквивалент aptitude почти для любой операционной системы, в том числе и для Mac OS X, для вас не составит никакого труда.
Руководство написно для версий Django 1.4 или выше. Если вы используете более раннюю версию, то вам придется самостоятельно найти wsgi модуль для нее. Также вы заметите, что файловая структура проекта будет немного отличаться от представленной здесь.
Общая идея
Веб-сервер может по запросу отдавать пользователям файлы из своей файловой системы, однако он не может напрямую работать с Djangо приложениями. Веб-серверу нужен интерфейс, который будет запускать Django приложение, передавать ему запрос от пользователя и возвращать ответ.
Для выполнения этих задач был разработан Web Server Gateway Interface — WSGI — стандарт взаимодействия Python программ и веб-сервра.
uWSGI — одна из реализаций WSGI. В этом руководстве мы установим и настроим uWSGI для создания Unix сокета и взаимодействия с веб-сервером по протоколу WSGI.
Полный стек компонентов будет выглядеть следующим образом:
Пользователь <-> Веб-сервер <-> Сокет <-> uwsgi <-> Django
Перед установкой uWSGI
virtualenv
Создадаем и активируем виртуальное окружение для софта, который нам будет необходим (ниже я расскажу, как установить uwsgi глобально):
virtualenv uwsgi-tutorial
cd uwsgi-tutorial
source bin/activate
Django
Устонавливаем Django в наше виртуальное окружение:
pip install Django
Создаем новый проект и переходим в его корневую папку:
django-admin.py startproject mysite
cd mysite
Домен и порт
В этом руководстве мы будем использовать для нашего учебного проекта домен yourserver.com. Вам нужно будет заменить его на собственное доменное имя или IP адрес вашего сервера.
Для получения запросов от пользователей мы будем использовать порт 8000. Вы можете использовать любой другой порт. Я выбрал именно 8000, потому что его использование не приведет к конфликтам с другими задачами, выполняемыми сервером.
Установка и базовая настройка uWSGI
Установка uWSGI в виртуальное окружение
Один из хороших способов установить uWSGI:
pip install uwsgi
Нам понадобятся Python development пакеты. Если вы используете Debian или основнную на Debian операционную систему (например, Ubuntu или Mint), вам нужно установить пакет pythonX.Y-dev, где X.Y — нужная вам версия Python.
Проверка
Создаем файл test.py:
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
Запускаем uWSGI:
uwsgi --http :8000 --wsgi-file test.py
Опции:
-
http: 8000
: используется протокол http и порт 8000
wsgi-file test.py
: uwsgi загрузит определенный файл (в нашем случае test.py)
В браузере переходим по адресу
http://yourserver.com:8000
.
Видим: «Hello, world», значит, мы все сделали правильно и следующие компоненты работают:
Пользователь <-> uWSGI <-> test.py
Проверка работы Django приложения
Теперь сделаем так, чтобы uWSGI работал с Django приложением, а не с файлом test.py.
Запускаем только что созданный проект mysite:
python manage.py runserver 0.0.0.0:8000
Запускаем uWSGI следующим образом:
uwsgi --http :8000 --module mysite.wsgi
-
module mysite.wsgi
: uwsgi загрузит модуль mysite.wsgi
В браузере переходим по адресу
http://yourserver.com:8000
.
Видим стартовую страницу Djangо, значит, мы все сделали правильно и следующие компоненты работают:
Пользователь <-> uWSGI <-> Django
Это нехорошо, что комьютер пользователя на прямую обращается к uWSGI. Между пользователем и uWSGI должен находиться веб-сервер.
Устновка и базовая настройка nginx
Установка и запуск nginx
sudo apt-get install nginx
sudo /etc/init.d/nginx start
Чтобы проверить, что nginx установлен и запущен, перейдите по адресу
http://yourserver.com:80
. Если вы видите сообщение “Welcome to nginx!”, значит, все окей и следующие компоненты работают:
Пользователь <-> Веб-сервер
Если у вас занят восьмидесятый порт, измените конфигурацию nginx так, чтобы он использовал какой-нибудь другой (в этом руководстве nginx будет использовать порт 8000).
Конфигурация nginx для работы с Django
Нам понадобится файл uwsgi_params, который можно взять здесь:
github.com/nginx/nginx/blob/master/conf/uwsgi_params.
Скачиваем его в корневую папку нашего проекта.
Создаем файл mysite_nginx.conf:
# mysite_nginx.conf
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # взаимодействие с uwsgi через Unix-сокет (мы воспользуемся этим вариантом позже)
server 127.0.0.1:8001; # взаимодействие с uwsgi через веб-порт
}
# конфигурация веб-сервера
server {
# порт, который будет слушать веб-сервер в ожидании запросов от пользователй
listen 8000;
# доменное имя
server_name yourserver.com; # замените на собственный домен или IP адрес
charset utf-8;
# максимальный размер загружаемых на сервер данных
client_max_body_size 75M;
# обслуживание медиа файлов и статики
location /media {
alias /path/to/your/mysite/media; # расположение медиафайлов (при необходимости измените)
}
location /static {
alias /path/to/your/mysite/static; # расположение статики (при необходимости измените)
}
# Остальные запросы перенаправляются в Django приложение
location / {
uwsgi_pass django;
include /path/to/your/mysite/uwsgi_params; # файл uwsgi_params, который мы только что взяли с github
}
}
Этот конфигурационный файл указывает nginx, что он должен отдавать пользователям медиа и статик файлы из файловой системы, а все остальные запросы перенаправлять в Django приложение. В больших проектах лучше использовать два сервера: один для обслуживания статик и медиа файлов, а другой для Django приложения. С небольшими, и тем более с учебными проектами, справится и один сервер.
В папке
/etc/nginx/sites-enabled
создаем ссылку на файл
mysite_nginx.conf
, чтобы nginx увидел его:
sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/
Статика в одном месте
Перед запуском nginx поместим всю статику в папку static. Для этого добавляем в файл mysite/settings.py следующую строку:
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
И выполняем команду:
python manage.py collectstatic
Проверка осблуживания статики и медиа
Перезапускаем nginx:
sudo /etc/init.d/nginx restart
Помещаем файл с именем, например, media.png в папку
/path/to/your/project/project/media
.
В браузере переходим по адресу
http://yourserver.com:8000/media/media.png
и, если видим наш файл, значит мы все сделали правильно.
nginx + uWSGI + test.py
Настраиваем взаимодействие nginx и test.py через uSWGI.
uwsgi --socket :8001 --wsgi-file test.py
Почти то же самое, что мы сделали недавано, за исключением одной опции:
-
socket :8001
: используем протокол uWSGI, порт 8001
Как вы помните, мы сконфигурировали nginx(файл
mysite_nginx.conf
) для работы с uWSGI через порт 8001.
Если перейти по адресу
http://yourserver.com:8001
, то мы ничего не увидим, поскольку браузер использует протокол http, а не uWSGI, однако uWSGI выведет сообщение о попытке соединения в терминал.
Unix сокеты вместо веб-портов
До этого мометна мы использовали сокет, привязанный к TCP порту (я называл его веб-порт), потому что так было проще, но на деле рекомендуется использовать Unix-сокет из-за преимущества в производительности.
Редактируем
mysite_nginx.conf
следующим образом:
server unix:///path/to/your/mysite/mysite.sock; # взаимодействие с uwsgi через Unix-сокет
# server 127.0.0.1:8001; # взаимодействие с uwsgi через веб-порт
И перезапускаем nginx:
sudo /etc/init.d/nginx restart
Запускаем uWSGI:
uwsgi --socket mysite.sock --wsgi-file test.py
На этот раз опция socket указывает на файл.
Открываем в браузере
http://yourserver.com:8000/
Если не заработало
Проверьте лог ошибок nginx, скорее всего он находится в файле
var/log/nginx/error.log
Если найдете там что-то похожее на
connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)
значит есть проблема с правами доступа к файлу mysite.sock. Необходимо сделать так, чтобы nginx имел разрешение на использование этого файла.
Попробуйте запустить uWSGI так:
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 #много полномочий
Или так:
uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 #более разумно
Чтобы проблем с доступом в будущем не было, добавьте вашего пользователя в группу www-data.
Информация, которую uWSGI выводит в терминал, полезна при поиске и исправлении возможных ошибок или неисправностей.
nginx + uWSGI + Django
Запускаем:
uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664
В браузере переходим на
http://yourserver.com:8000/
и видим стартовую страницу Django.
Пользователь <-> Веб-сервер <-> Сокет <-> uwsgi <-> Django
Мы собрали всю цепочку, но настройка еще не закончена, идем дальше.
Конфигурация uWSGI через ini файл
Очень удобно все опции, с которыми мы запускаем uWSGI, указать в ini файле, а при запуске передавать только путь к этому файлу.
Создаем файл
mysite_uwsgi.ini
:
#mysite_uwsgi.ini
[uwsgi]
# Настройки, связанные с Django
# Корневая папка проекта (полный путь)
chdir = /path/to/your/project
# Django wsgi файл
module = project.wsgi
# полный путь к виртуальному окружению
home = /path/to/virtualenv
# общие настройки
# master
master = true
# максимальное количество процессов
processes = 10
# полный путь к файлу сокета
socket = /path/to/your/project/mysite.sock
# права доступа к файлу сокета
# chmod-socket = 664
# очищать окружение от служебных файлов uwsgi по завершению
vacuum = true
Запускаем uWSGI:
uwsgi --ini mysite_uwsgi.ini
Проверяем. Все работает? Дальше.
Устанавливаем uWSGI глобально
До сих пор uWSGI был установлен в виртуальном окружении. Чтобы была возможность автоматически запускать uWSGI при старте операционной системы, мы установим его глобально.
Деактивируем виртуальное окружение:
deactivate
Устанавливаем uwsgi:
sudo pip install uwsgi
# Или можно установить LTS (с долговременной поддержкой) версию
pip install http://projects.unbit.it/downloads/uwsgi-lts.tar.gz
На вики странице uWSGI описано несколько
вариантов установки. Перед тем, как установить uWSGI глобально, вам не помешает определиться с выбором версии и методом установки.
Запусить uWSGI можно той же командой, что и раньше:
uwsgi --ini mysite_uwsgi.ini
Режим Emperor
Если сервер обслуживает несколько проектов, каждый из которых использует uWSGI, то нужно исползовать режим Emperor. В этом режиме uWSGI просматривает папку с конфигурационными файлами и для каждого файла запускает отдельный процесс (вассал).
Если один из конфигурационных файлов будет изменен, uWSGI перезапустит соответствующего вассала.
Создаем папку для конфигурационных файлов:
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals
Создаем в ней ссылку на mysite_uwsgi.ini:
sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/
Запускаем uWSGI в режиме Emperor:
sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
Опции:
emperor
: папка с конфигурациолнными файлами
uid
: id пользователя, от имени которого будет запущен процесс
gid
: id группы, от имени которой будет запущен процесс
Проверяем.
http://yourserver.com:8000/
Автоматичесеий запуск uWSGI после загрузки операционной системы
В файл
/etc/rc.local
, перед строкой “
exit 0
” добавляем:
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
Дело сделано.