Django в production [Nginx + uWSGI + Django]

Блог / Фреймворк Django

Когда впервые столкнулся с вопросом развертывания Django проекта, мне это казалось сложным, ведь цепочка компонентов получается большая. Однако, это только на первый взгляд. Запуск будет происходить по такой цепочке компонентов:

Nginx -> socket -> uWSGI -> Django

Также, текущая инструкция будет следовать ряду правил.

  • Все статичные файлы будут отдаваться только Nginx
  • Nginx и uWSGI будут взаимодействовать посредством UNIX-сокетов
  • За работой uWSGI будет следить Supervisor

Инструкция предполагает, что у вас уже создан проект на фреймворке Django, и написан requirements.txt для быстрой вставки пакетов в VirtualEnv.

1. Установка компонентов

1.1. Установка Nginx

Если вас не беспокоит неактуальная версия пакета Nginx, то его можно установить из менеджера пакетов:

$ sudo apt-get install nginx

Однако, я бы советовал установить Nginx, следуя официальной инструкции.

1.2 Установка uWSGI

Как и многое для языка Python, установка uWSGI разделяется на два варианта: для python2 и для python 3.

1.2.1 Установка uWSGI для Python 2.x

Устанавливаем PIP

$ sudo apt-get install python-pip

Устанавливаем uWSGI

$ sudo pip install uwsgi

1.2.2 Установка uWSGI для Python 3.x

Устанавливаем PIP3

$ sudo apt-get install python3-pip

Устанавливаем uWSGI

# pip3 install uwsgi

1.3 Установка Virtualenv

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

$ sudo pip install virtualenv

для Python 2.x, или для python 3.x

$ sudo pip3 install virtualenv

1.4 Установка Supervisor

Supervisor нам понадобится для того, чтобы контроллировать состояние работы uWSGI, запускать его при запуске системы, и перезапускать в случае его аварийной остановки. Установить его нужно командой:

$ sudo apt-get install supervisor

2. Заливка Virtualenv и Django

Переходим в папку, где будем хранить наше виртуальное окружение Python

$ cd /path/to/env

Затем создаем наше виртуальное окружение

$ virtualenv --no-site-packages -p pythonX.X <env_name>

где:

  • <env_name> - имя виртуального окружения (вводится без "<", ">")
  • --no-site-packages - установка Virtualenv, запрещающая наследовать пакеты глобального окружения
  • pythonX.X - нужная вам версия python

Теперь накатим все зависимости из файла requirements.txt. Для этого активируем окружение

$ source /path/to/env/bin/activate

И установим пакеты

$ pip install -r /path/to/requirements.txt #или pip3 install...

Также, нам следует залить наш Django проект на сервер удобным для вас способом.

3. Подготовка файлов

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

/configs
    /nginx.conf
    /uwsgi.ini
    /supervisor.conf

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

3.1 Файл nginx.conf

upstream django {
    server unix:///path/to/socket;
}

server {
    listen          80;
    server_name     example.com;
    charset         utf-8;

    client_max_body_size 10M;

    location /media  {
        alias /path/to/media;
    }

    location /static {
        alias /path/to/static;
    }

    location / {
        uwsgi_pass  django;

        uwsgi_param  QUERY_STRING       $query_string;
        uwsgi_param  REQUEST_METHOD     $request_method;
        uwsgi_param  CONTENT_TYPE       $content_type;
        uwsgi_param  CONTENT_LENGTH     $content_length;

        uwsgi_param  REQUEST_URI        $request_uri;
        uwsgi_param  PATH_INFO          $document_uri;
        uwsgi_param  DOCUMENT_ROOT      $document_root;
        uwsgi_param  SERVER_PROTOCOL    $server_protocol;
        uwsgi_param  REQUEST_SCHEME     $scheme;
        uwsgi_param  HTTPS              $https if_not_empty;

        uwsgi_param  REMOTE_ADDR        $remote_addr;
        uwsgi_param  REMOTE_PORT        $remote_port;
        uwsgi_param  SERVER_PORT        $server_port;
        uwsgi_param  SERVER_NAME        $server_name;
    }
}

Файл конфигурации Nginx.

  • upstream django - подключение к файлу сокета uwsgi. Этот сокет будет обозначен в файле конфигурации uwsgi, будет создаваться при запуске uwsgi, и будет удаляться при остановке uwsgi.
  • listen - прослушиваем 80 порт. Стандартный порт для подачи запросов браузерами.
  • server_name - адрес вашего сайта. На этап тестирования можно указать IP сервера, либо 'localhost' (если сервер будет запускаться локально)
  • client_max_body_size - максимальный размер тела запроса. Необязательно. Дополнительная подстраховка.
  • location /media и location /static - путь к папкам media и static файлов Django. Если nginx встречает адрес, который начинается с /media или /static, то он не отдает запрос uWSGI, а пытается сам отдать файл находящийся в указанной папке. У вас могут быть свои имена папок и путей URL.
  • location / - параметры подключения к uWSGI, где uwsgi_pass - имя upstream для подключения. Остальные параметры лучше не менять.

3.2 Файл uwsgi.ini

[uwsgi]
uid             = www-data
gid             = www-data
env             = LANG=en_US.UTF-8
env             = DJANGO_SETTINGS_MODULE=project.settings
plugins         = python3
master          = true
virtualenv      = /path/to/virtualenv
chmod-socket    = 664
socket          = /path/to/socket
chdir           = /path/to/project
pythonpath      = /path/to/project
wsgi-file       = /path/to/project/uwsgi.py
processes       = 5
enable-threads  = true
vacuum          = true

Файл настроек, с которым будет запускаться uWSGI.

  • uid и gid - пользователь и группа пользователей linux, от имени которых будет запускаться uWSGI-вассал
  • virtualenv - пусть до виртуального окружения
  • chmod-socket - права, с которыми будет создаваться soket-файл
  • socket - произвольный путь к папке, где будет создан socket
  • chdir и pythonpath - указываем путь до проекта
  • env - дополнительные атрибуты виртуального окружения. Указываем обязательный параметр DJANGO_SETTINGS_MODULE, где project - папка, в которой лежит settings.py
  • processes - число воркеров, запускаемых для обслуживания проекта. Для каждого проекта подбирается отдельно

Хочу заметить, что socket должен быть доступен для чтения и записи как uWSGI, так и nGINX. Лучший вариант для избежания ошибок - назначить для Nginx того же пользователя, что и для uwsgi, а также передать права на проект и папку с сокетом этому пользователю. Худший вариант - ослабить права chmod-socket.

3.3. Файл supervisor.conf

[program:uwsgi]
user = www-data
directory = /path/to/project
command = uwsgi --emperor /path/to/vassals --uid www-data --gid www-data
autostart = true
autorestart = true
stderr_logfile = /var/log/supervisor/site_uwsgi_err.log
stdout_logfile = /var/log/supervisor/site_uwsgi_out.log
stopsignal = QUIT

Конфигурационный файл, который будет запускать и отслеживать процесс с названием uwsgi

  • user - пользователь linux, с помощью которого будет запускаться процесс
  • directory - директория, с которой будет выполняться команда. Может быть любой
  • command - команда, с помощью которой будет запускаться процесс. Сразу заметим, что мы будем запускать uWSGI в режиме EMPEROR, позволяющего запускать несколько сайтов на одном сервере. Сразу определяемся с папкой, где будут храниться конфиги вассалов (сайт = вассал).
  • stderr_logfile и stdout_logfile - файлы логов.

4. Создание симлинков

Итак, все файлы готовы. Осталось разложить их по правильным местам. Для начала создадим симлинк для Nginx.

$ sudo ln -s /path/to/nginx.conf /etc/nginx/conf.d/site.conf

В случае, если мы будем запускать на сервере несколько файлов, мы не сможем в одну папку конфига ложить файлы с одним и тем же именем, поэтому мы создаем симлинк с нашим файлом nginx.conf в папке Nginx, как имя_сайта.conf.

Затем, копируем конфиг uWSGI в папку вассалов.

$ sudo ln -s /path/to/uwsgi.ini /path/to/vassals/site.ini

И создаем симлинк для конфигурации supervisor

$ sudo ln -s /path/to/supervisor.conf /etc/conf.d/uwsgi.conf

5. Запуск

Для начала запускаем uWSGI с помощью supervisor, чтобы создался сокет. Затем перезапускаем Nginx.

Запускаем процесс uwsgi:

# supervisorctl start uwsgi

И перезапускаем Nginx:

# service nginx restart

6. Проверка

Идем в файл логов /var/log/supervisor/site_uwsgi_err.log, последние строки должны сообщать о запуске вассала site.ini и запущенных для него воркеров.

*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 1866)
Thu Jun  1 00:52:07 2017 - [emperor] vassal site.ini has been spawned
spawned uWSGI worker 1 (pid: 1868, cores: 1)
spawned uWSGI worker 2 (pid: 1869, cores: 1)
spawned uWSGI worker 3 (pid: 1870, cores: 1)
spawned uWSGI worker 4 (pid: 1871, cores: 1)
spawned uWSGI worker 5 (pid: 1872, cores: 1)

Также, можно посмотреть логи Nginx - /var/log/nginx/error.log. Если ошибок при подключении не было, то и записей никаких, как правило, не возникает.

 

Денис Каримов

Django production

Эта запись входит в ряд записей "Django production"

Комментарии
Написать комментарий

Написать комментарий

2017г. Karimov.info