Установка uWSGI + Nginx для Django на Ubuntu 16.04 LTS

Когда-то я уже описывал как ставится похожий стек на систему Ubuntu 14.04 LTS. Данная инструкция во многом похожа, за исключением нескольких нюансов, которые стоят того, чтобы её обновить. То ли сказывается опыт после многочисленных повторов этого процесса, то ли программное обеспечение улучшается, но со временем это становится делать все более удобно. Почему я ставлю только LTS, а не пользуюсь самыми последними версиями Ubuntu Server? Потому что LTS надежнее (more tested) и дольше поддерживается.

Оглавление

1. Установка ПО

Устанавливаем все, что нам понадобится:

sudo apt-get install build-essential python-dev libpcre3 libpcre3-dev nginx

Далее, устанавливаем виртуальное окружение куда вам удобно привычно и удобно. В последнее время стало популярно пользоваться virtualenvwrapper, чье название говорит само за себя. Я попробовал, но мне не очень понравилось. Что ни говорите, а быстрее и привычнее работать непосредственно с virtualenv, это, скорее, дело вкуса и привычки.

sudo pip3 install uwsgi

Все новые проекты в последнее время я стараюсь (если в требованиях не указано иное) разрабатывать на Python 3. Однако в Ubuntu 16.04 по умолчанию все еще используется Python, поэтому uwsgi устанавливаем с помощью pip3. Но если третий Python не нужен, тогда, как обычно, ставим с помощью pip.

2. Настройка uwsgi

Как и прежде, конфигурации uwsgi, nginx, логи, а также виртуальное окружение я складываю в соседние с проектом каталогах. Многие предпочитают другой порядок — виртуальные окружения в одном месте, логи в /var/log/, конфигурации uwsgi - в /etc/uwsgi/, конфигурации nginx - в /etc/nginx/. Что касается uwsgi и nginx, то у меня тоже есть эти папки, но там лежат симлинки на конфиги, которые на самом деле хранятся рядом с проектом.

Обратите внимание, что файлы конфигурации для uwsgi обязательно должны иметь расширение .ini или .conf

«Императорский» конфиг положим в файл /etc/uwsgi/emperor.ini

[uwsgi]
emperor = /etc/uwsgi/vassals
uid = django
gid = django
master = true
enable-threads = true

Допустим, все django-проекты хранятся в /home/django/. Тогда типовая конфигурация будет такой

[uwsgi]
socket = /tmp/%n.sock
chmod-socket = 666
logfile-chown = true

processes = 1
threads = 2
offload-threads = 2

virtualenv = /home/django/%n/venv/
chdir = /home/django/%n/%n
wsgi-file = %n/wsgi.py
vacuum = true

logto = /home/django/%n/deploy/logs/uwsgi.log

ignore-sigpipe = true
ignore-write-errors = true
disable-write-exception = true

Здесь ничего особенного, все как предлагается в документации для типового проекта в режиме Emperor. Обратите внимание, что вместо %n будет подставлено имя файл конфигурации без .ini. Таким образом можно хранить эту конфигурация, скажем, в файле /etc/uwsgi/vassals/_skeleton, а для конфигураций конкретных проектов создавать симлинки

sudo ln -s /etc/uwsgi/vassals/_skeleton /etc/uwsgi/vassals/newproject.ini

Последние три строчки нужны, чтобы избавиться от ошибки IOError: write error, которая выбрасывается в Sentry, даже если все работает нормально.

Примечание 1: Если uwsgi будет работать в обычном режиме (не Emperor), тогда вместо logto пишем daemonize с тем же значением.

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

3. Как запускать uwsgi

uwsgi --emperor /etc/uwsgi/vassals

Начиная с Ubuntu 15 менеджером запуска по умолчанию стал systemd вместо upstart. Поэтому теперь он будет управлять запуском uwsgi при загрузке сервера. В файле /etc/systemd/system/emperor.uwsgi.service задаем такие параметры (для режима Emperor):

[Unit]
Description=uWSGI Emperor
After=syslog.target

[Service]
ExecStart=/usr/local/bin/uwsgi --ini /etc/uwsgi/emperor.ini
# Requires systemd version 211 or newer
RuntimeDirectory=uwsgi
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

Затем запускаем

sudo systemctl start emperor.uwsgi.service

Проверим состояние командой

systemctl status emperor.uwsgi.service

Получим примерно такой вывод на экран консоли:

emperor.uwsgi.service - uWSGI Emperor
  Loaded: loaded (/etc/systemd/system/emperor.uwsgi.service; disabled; vendor preset: enabled)
  Active: active (running) since Thu 2017-04-20 08:24:37 UTC; 2 days ago
Main PID: 3715 (uwsgi)
  Status: "The Emperor is governing 1 vassals"
  CGroup: /system.slice/emperor.uwsgi.service
          ├─ 3715 /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals
          ├─15570 /usr/local/bin/uwsgi --ini myproj.ini
          └─15573 /usr/local/bin/uwsgi --ini myproj.ini
Все в порядке, подключаем службу
sudo systemctl enable uwsgi

4. Настройка Nginx

Простейшая конфигурация Nginx:

server {
    server_name myproj.com;
    access_log /home/django/myproj/deploy/logs/nginx_acc.log;
    error_log /home/django/myproj/deploy/logs/nginx_err.log;

    location / {
        uwsgi_pass      unix:///tmp/uwsgi.sock;
        include         uwsgi_params;
    }

    location ~ ^/(static|media)/ {
          root /home/django/myproj/myproj;
          expires max;
    }
}

Далее перезагружаем nginx. На этом этапе, если все домены правильно настроены, сайт должен загружаться в браузере.

Конечно, конфигурация nginx показана в простейшем варианте, но она уже работает. Остальные параметры — в документации.

Возможно, вам будет интересно