Обслуживание приложений Django с помощью uWSGI и Nginx в Debian 8

Django – это производительный веб-фреймворк для разработки приложений или сайтов в Python. Django также предоставляет простой сервер разработки для локального тестирования кода. К сожалению, для производства  необходимо искать более безопасный и мощный веб-сервер, так как этот сервер совершенно не подходит.

Данное руководство поможет установить и настроить в Debian 8 все компоненты, необходимые для поддержки приложения и обработки клиентских запросов. Для этого будет использоваться сервер приложений uWSGI и обратный прокси-сервер Nginx.

Требования

Для выполнения данного руководства нужно предварительно настроить сервер Debian 8 и создать пользователя с доступом к sudo. Подробные инструкции по начальной настройке сервера и созданию пользователей можно найти здесь.

Фреймворк Django в данном руководстве будет установлен в два разных виртуальных окружения Python, что позволит удовлетворить все индивидуальные требования каждого приложения.

После запуска приложения нужно настроить сервер приложений uWSGI, который будет использоваться в качестве интерфейса приложения и переформатировать запросы HTTP в вызовы Python. После этого нужно настроить обратный прокси-сервер Nginx.

Установка и настройка VirtualEnv и VirtualEnvWrapper

Проекты Django будут установлены в индивидуальное виртуальное окружение. Для этого нужно установить инструменты virtualenv (создаёт виртуальную среду Python) и virtualenvwrapper (добавляет несколько полезных функций virtualenv).

Для установки инструментов используйте pip, пакетный менеджер Python. Установить pip можно из официального репозитория Debian.

# Python 2:
sudo apt-get update
sudo apt-get install python-pip
# Python 3:
sudo apt-get update
sudo apt-get install python3-pip

Теперь выполните глобальную установку virtualenv и virtualenvwrapper.

# Python 2:
sudo pip install virtualenv virtualenvwrapper
# Python 3:
sudo pip3 install virtualenv virtualenvwrapper

Теперь можно настроить оболочку с помощью сценария virtualenvwrapper. Все виртуальные окружения будут помещены в каталог Env в домашнем каталоге. Чтобы настроить это, используется переменная WORKON_HOME. Добавьте её в сценарий инициализации оболочки.

Примечание: При использовании Python 3 и pip3 нужно добавить дополнительную строку в сценарий инициализации.

echo "export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc

Независимо от версии Python запустите следующие команды:

echo "export WORKON_HOME=~/Env" >> ~/.bashrc
echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.bashrc

Чтобы иметь доступ к новым функциям в текущей сессии, выполните команду:

source ~/.bashrc

Теперь в домашнем каталоге есть каталог Env, в котором хранятся виртуальные окружения проектов.

Создание проектов Django

Теперь нужно создать два виртуальных окружения и запустить два проекта.

Создание первого проекта Django

Создайте виртуальное окружение с помощью команд, доступных благодаря инструменту virtualenvwrapper.

Чтобы создать первое виртуальное окружение, введите:

mkvirtualenv firstsite

Эта команда создаст виртуальное окружение по имени firstsite, а также установит локальную версию Python и pip, которые можно использовать для создания изолированной среды разработки проекта. Командная строка изменится, указывая, что текущей средой является виртуальная среда Python:

(firstsite)user@hostname:~$

В скобках указано имя текущего виртуального окружения. Теперь всё программное обеспечение, загруженное с помощью pip, будет установлено в индивидуальное окружение первого проекта и никак не повлияет на общее состояние системы.

Сначала нужно установить Django:

pip install django

Теперь создайте первый тестовый проект:

cd ~
django-admin.py startproject firstsite

Эта команда создаст в домашнем каталоге каталог firstsite. В нём хранится сценарий для управления новым проектом и ещё один одноимённый каталог, в котором будет находиться код проекта.

Откройте каталог первого уровня:

cd ~/firstsite

Для начала нужно переместить БД, чтобы инициализировать базу данных SQLite для проекта.

Примечание: При желании можно создать базу данных для приложения самостоятельно, но это выходит за рамки данного руководства.

./manage.py migrate

Теперь в домашнем каталоге есть файл БД по имени db.sqlite3. Создайте администратора.

./manage.py createsuperuser

Выберите имя пользователя, укажите контактный адрес электронной почты, а затем выберите и подтвердите пароль.

Затем откройте файл настроек проекта:

nano ~/firstsite/firstsite/settings.py

Найдите директиву ALLOWED_HOSTS. Она определяет белый список адресов и доменов, которые могут подключаться к проекту Django. С помощью этой директивы Django может предотвратить определенные уязвимости в системе безопасности.

Перечислите заведомо безопасные IP-адреса и доменные имена в квадратных скобках. Каждый элемент нужно взять в кавычки. Элементы отделяются запятыми. Чтобы внести в белый список поддомены какого-либо доменного имени, поставьте в начале этого домена точку. Ниже приведено несколько примеров таких настроек:

. . .
# самый простой список IP-адресов и доменов сервера Django
# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5'] # Чтобы добавить в список поддомены домена example.com, поставьте точку в начале домена
# ALLOWED_HOSTS = ['.example.com', '203.0.113.5'] ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . .]

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

. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Сохраните и закройте файл. Соберите статические файлы в этом каталоге:

./manage.py collectstatic

В каталоге проекта появится новый каталог static.

Чтобы получить доступ к серверу разработки Django, нужно отредактировать настройки брандмауэра. Откройте порт 8080:

# ufw
sudo ufw allow 8080
# iptables
sudo iptables -I INPUT -p tcp --dport 8080 -j ACCEPT

Читайте также: Настройка фаервола с помощью IPTables на Ubuntu 14.04

Теперь протестируйте проект, временно запустив сервер разработки.

./manage.py runserver 0.0.0.0:8080

Это запустит сервер разработки на порт 8080. В браузере посетите свой домен или IP:

http://server_domain_or_IP:8080

На экране должна появиться такая страница:

It worked!
Congratulations on your first Django-powered page. [...]

Добавьте в ссылку сегмент /admin, чтобы получить доступ к форме аутентификации администратора. Введите учётные данные администратора, и на экране появится панель управления.

После этого можно остановить сервер разработки. Нажмите CTRL-C в терминале. Теперь можно приступать к разработке второго проекта.

Разработка второго проекта

Второй проект создаётся точно так же, как первый.

Вернитесь в домашний каталог и создайте второе виртуальное окружение. Установите Django.

cd ~
mkvirtualenv secondsite
pip install django

После этого откроется окружение нового проекта.

Создайте второй проект и откройте его каталог:

django-admin.py startproject secondsite
cd ~/secondsite

Инициализируйте базу данных и создайте пользователя с правами администратора:

./manage.py migrate
./manage.py createsuperuser

Откройте файл settings:

nano ~/secondsite/secondsite/settings.py

Добавьте белый список второго пректа с помощью ALLOWED_HOSTS:

ALLOWED_HOSTS = ['second_project_domain_or_IP', 'another_domain_or_IP', . . .]

Затем укажите каталог статических файлов:

. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')

Сохраните и закройте файл.

Соберите статические файлы в этот каталог.

./manage.py collectstatic

Запустите сервер разработки:

./manage.py runserver 0.0.0.0:8080

Сайт будет доступен по ссылке:

http://server_domain_or_IP:8080

Интерфейс администратора:

http://server_domain_or_IP:8080/admin

Чтобы остановить сервер, нажмите CTRL-C.

Отключение виртуального окружения

Теперь нужно отключить виртуальное окружение, поскольку разработка проектов завершена:

deactivate

Чтобы вернуться в виртуальное окружение любого из проектов, введите:

workon firstsite
# или
workon secondsite

В дальнейшей работе виртуальное окружение не нужно, потому отключите его.

Сервер приложений uWSGI

Теперь нужно настроить uWSGI – сервер приложений, взаимодействующий с приложениями с помощью простого интерфейса WSGI.

Читайте также: Настройка uWSGI и Nginx для обслуживания приложений Python

Установка uWSGI

В данном руководстве нужно установить uWSGI глобально – так будет проще обрабатывать несколько проектов Django.

Установите зависимости сервера:

# Python 2:
sudo apt-get install python-dev
# Python 3:
sudo apt-get install python3-dev

Теперь установите uWSGI.

# Python 2:
sudo pip install uwsgi
# Python 3:
sudo pip3 install uwsgi

Чтобы быстро протестировать сервер, передайте ему данные одного из сайтов. Например, можно попробовать обслужить первый проект:

uwsgi --http :8080 --home /home/8host/Env/firstsite --chdir /home/8host/firstsite -w firstsite.wsgi

Теперь uWSGI использует виртуальное окружение каталога ~/Env, чтобы получить доступ к каталогу проекта и использовать файл wsgi.py для обслуживания проекта. Сервер обслуживает HTTP на порте 8080. Откройте доменное имя или IP-адрес сервера в браузере, укажите порт 8080 (статические элементы интерфейса, как CSS, например, не будут работать).чтобы остановить сервер, нажмите CTRL-C.

Создание конфигурационного файла

Запуск uWSGI из командной строки хорошо подходит для тестирования, но в реальном развёртывании это очень неудобно. Запустите сервер в режиме Emperor mode, что позволяет ведущему процессу управлять отдельными приложениями автоматически. Для этого используются конфигурационные файлы.

Создайте каталог для хранения таких файлов.

sudo mkdir -p /etc/uwsgi/sites
cd /etc/uwsgi/sites

Теперь нужно создать конфигурационный файл для каждого проекта. uWSGI может читать конфигурации разных форматов. В данном руководстве используется формат ini.

Создайте файл для первого проекта:

sudo nano firstsite.ini

Добавьте заголовок [uwsgi], под которым нужно поместить все настройки. Добавьте несколько переменных, чтобы сделать файл более универсальным. Сразу после заголовка добавьте переменную project с именем проекта. Переменная uid будет хранить имя пользователя с доступом к sudo.

Затем добавьте переменную base, в которой нужно указать путь к домашнему каталогу. Для этого используется синтаксис: %(переменная).

[uwsgi] project = firstsite
uid = 8host
base = /home/%(uid)

Теперь нужно настроить uWSGI для поддержки проекта. Добавьте опцию chdir, чтобы указать корневой каталог проекта. Импортируйте callable application из файла wsgi.py в каталоге проекта.

[uwsgi] project = firstsite
uid = 8host
base = /home/%(uid)
chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

Создайте главный процесс с 5 рабочими процессами.

[uwsgi] project = firstsite
uid = 8host
base = /home/%(uid)
chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application
master = true
processes = 5

Теперь нужно настроить прослушивание соединений. Ранее для тестирования uWSGI использовались HTTP и сетевой порт, но есть варианты и получше. Например, вместо порта можно использовать сокет. Этот вариант безопаснее и обеспечивает более высокую производительность. Сокеты используют не HTTP, а uwsgi – быстрый бинарный протокол для взаимодействия uWSGI с другими серверами. Nginx имеет встроенную поддержку uwsgi при проксировании.

Также следует изменить права на сокет. Опция vacuum автоматически очистит файл сокета после остановки сервиса.

[uwsgi] project = firstsite
uid = 8host
base = /home/%(uid)
chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application
master = true
processes = 5
socket = /run/uwsgi/%(project).sock
chown-socket = %(uid):www-data
chmod-socket = 660
vacuum = true

Настройка первого проекта завершена. Сохраните и закройте файл.

Преимущество переменных в конфигурационных файлах состоит в том, что их можно использовать повторно. Скопируйте файл первого проекта и используйте его в качестве шаблона для настройки второго сайта.

sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini

Откройте скопированный файл:

sudo nano /etc/uwsgi/sites/secondsite.ini

В файле нужно изменить только переменную project.

[uwsgi] project = secondsite
uid = 8host
base = /home/%(uid)
chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application
master = true
processes = 5
socket = /run/uwsgi/%(project).sock
chown-socket = %(uid):www-data
chmod-socket = 660
vacuum = true

Сохраните и закройте файл.

Unit-файл для uWSGI

Django-проекты обслуживаются сервером приложений. Теперь нужно автоматизировать этот процесс. Для этого создайте unit-файл.

sudo nano /etc/systemd/system/uwsgi.service

Файл начинается с раздела [Unit], в котором хранятся метаданные и другая информация о сервисе (например, его описание).

[Unit] Description=uWSGI Emperor service

Затем добавьте раздел [Service]. Директива ExecStartPre запускает указанные в ней компоненты. В данном случае она создаст каталог /run/uwsgi, принадлежащий текущему пользователю и группе www-data.

Директива ExecStart запускает сервис, в данном случае uwsgi в режиме Emperor mode. Также нужно добавить компоненты, необходимые для поддержки процесса system. Больше настроек можно найти в документации uWSGI.

[Unit] Description=uWSGI Emperor service
[Service] ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown 8host:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

Теперь осталось добавить раздел [Install]. Он отвечает за автоматический запуск сервиса. Настройте сервис для работы в многопользовательской системе.

[Unit] Description=uWSGI Emperor service
[Service] ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown 8host:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install] WantedBy=multi-user.target

Сохраните и закройте файл.

Пока что запустить этот сервис невозможно, поскольку он зависит от пользователя www-data. Сервис будет доступен после установки и настройки Nginx.

Nginx как обратный прокси-сервер

Загрузите пакет Nginx из стандартного репозитория Debian.

sudo apt-get install nginx

После установки Nginx создайте виртуальный хост (блок server) для каждого проекта.

sudo nano /etc/nginx/sites-available/firstsite

Теперь у вас есть конфигурационный файл для первого проекта.

Чтобы указать домен первого проекта, добавьте в файл такой код:

server {
listen 80;
server_name firstsite.com www.firstsite.com;
}

Укажите местонахождение статических файлов.

server {
listen 80;
server_name firstsite.com www.firstsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/8host/firstsite;
}
}

Добавьте блок location для обслуживания всех остальных запросов. Добавьте параметры uwsgi из файла /etc/nginx/uwsgi_params и передайте трафик на сокет:

server {
listen 80;
server_name firstsite.com www.firstsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/8host/firstsite;
}
location / {
include         uwsgi_params;
uwsgi_pass      unix:/run/uwsgi/firstsite.sock;
}
}

Сохраните виртуальный хост.

Используйте этот файл как шаблон для виртуального хоста второго проекта.

sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite

Откройте новый файл:

sudo nano /etc/nginx/sites-available/secondsite

Замените все данные о firstsite информацией о secondsite. Измените server_name, указав домен второго проекта. В результате должно получиться так:

server {
listen 80;
server_name secondsite.com www.secondsite.com;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/8host/secondsite;
}
location / {
include         uwsgi_params;
uwsgi_pass      unix:/run/uwsgi/secondsite.sock;
}
}

Сохраните и закройте файл.

Создайте ссылки на новые конфигурационные файлы в каталоге sites-enabled.

sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/secondsite /etc/nginx/sites-enabled

Проверьте файлы на наличие ошибок:

sudo nginx –t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Если ошибок нет, перезапустите сервис Nginx:

sudo systemctl restart nginx

Теперь можно запустить сервер приложений uWSGI.

sudo systemctl start uwsgi

Удалите правило UFW для порта 8080 и разблокируйте доступ к серверу Nginx.

# ufw
sudo ufw delete allow 8080
sudo ufw allow 'Nginx Full'
# iptables
sudo iptables -D INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT

Теперь оба проекта доступны по доменным именам. Проверьте работу проектов и интерфейсов. Если всё работает должным образом, настройте автозапуск сервисов:

sudo systemctl enable nginx
sudo systemctl enable uwsgi

Примечание: После настройки обратного прокси-сервера Nginx настоятельно рекомендуется защитить подключения при помощи сертификатов SSL/TLS. В противном случае все данные будут передаваться в виде простого текста и легко могут быть перехвачены злоумышленниками. Сервис Let’s Encrypt позволяет получить бесплатный сертификат. Подробнее об этом – здесь.

Если же у вас нет доменного имени, вы можете создать самоподписанный сертификат.

Заключение

Теперь сервер приложений uWSGI обслуживает два приложения Django, которые находятся в индивидуальных виртуальных окружениях.

Tags: , , , ,

Добавить комментарий