Деплой проекта Django в продакшн с Nginx + Gunicorn + Supervisor

👁 388 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

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

  • Nginx — WEB-сервер;
  • Gunicorn — HTTP-сервер Python WSGI;
  • Supervisor — менеджер процессов.

Исходные данные

Для использования данного поста требуются следующие исходные данные по ПО:

  • готовый удаленный сервер Linux в виде VPS/VDS с выделенным IP;
  • установленный и настроенный Python 3 c виртуальными средами и разрабатываемым проектом на Django;

Исходные данные по неймингу:

  • /home/myprojectenv/ — абсолютный путь к папке виртуальной среды;
  • /home/myprojectenv/myproject/ — абсолютный путь к папке проекта на Django;
  • (myprojectenv)user@host: /myprojectenv/ —  вид строки запроса в консоли под активной виртуальной средой Python;
  • 11.22.33.44IP нашего удаленного сервера VDS/VPS;
  • 8000 — порт, на котором будет подвешен наш проект.

 

Установка и настройка Nginx и Gunicorn

Для начала нужно сделать апгрейд

sudo apt-get update
sudo apt-get upgrade

Ставим Nginx

sudo apt-get install nginx

Теперь заходим под виртуальную среду нашего(или вашего) проекта

cd /home/myprojectenv/
source bin/activate

Под активной виртуальной средой ставим Gunicorn

(myprojectenv)user@host: /home/myprojectenv# pip[pip3] install gunicorn

Замечание. Помните про версии pip. Если Python 2.x, то пишем pip, если Python 3.xpip3. Это по дефолту, если у вас не настроено иначе.

Теперь, перед тем, как идти дальше, протестируем удачную установку Gunicorn и интеграцию с проектом Django и для этого выполняем команду

(myprojectenv)user@host: /home/myprojectenv/myproject# gunicorn myproject.wsgi:application --bind 11.22.33.44:8000

Идем в браузер и запускаем по адресу страницу 11.22.33.44:8000 и убеждаемся, что все ок.

Далее настраиваем папку статических файлов и для этого открываем файл настроек проекта в папке /home/myprojectenv/myproject/myproject/settings.py

nano settings.py

Добавляем в этот файл параметр STATIC_ROOT, если его нет, со следующим значением

...
STATIC_ROOT = '/home/myprojectenv/myproject/static/'
...

Сохраняем, выходим и далее выполняем из папки проекта команду

(myprojectenv)user@host: /home/myprojectenv/myproject# python manage.py collectstatic

После чего в папке проекта появится новая папка с именем static.

Теперь идем и настраиваем Nginx по пути в файле

cd /etc/nginx/sites-available/

открываем файлик default

nano default

и перепишем некоторые моменты, как ниже

server {
    listen 80;
    server_name 11.22.33.44; #либо ip, либо доменное имя
    access_log  /var/log/nginx/example.log;

    location /static/ {
        root /home/myprojectenv/myproject/;
        expires 30d;
    }

    location / {
        proxy_pass http://127.0.0.1:8000; 
        proxy_set_header Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }

сохраняем и выходим.

Выполняем перезапуск Nginx, чтобы изменения вступили в силу

sudo service nginx restart

 

Активируем нашу среду и заходим в папку проекта для проверки запуска в связке Gunicon + Nginx

(myprojectenv)user@host: /home/myprojectenv/myproject# gunicorn myproject.wsgi:application

В браузере набираем 11.22.33.44:8000 и убеждаемся, что все ок.

Установка и настройка Supervisor

Чтобы ваше приложение стартовало после любого непредвиденного рестарта системы или сбоя, нам нужно использовать в деле supervisor.

Установим supervisor

apt-get install supervisor

Создадим конфигурационный файл для gunicorn в подпапке проекта (myproject/myproject/) рядом с settings.py

cd /home/myprojectenv/myproject/myproject
touch gunicorn.conf.py
nano gunicorn.conf.py

и записываем туда такие данные, которые означают, что данный проект будет запущен на IP и порте 0.0.0.0:8000, что будет означать внешний адрес нашего VPS. Если у вас сервер локальный, то ставим 127.0.0.1

bind = '0:8000'
workers = 3
user = "nobody"

Теперь создаем конфигурационный файл для supervisor

cd /etc/supervisor/conf.d/
touch myproject.conf
nano myproject.conf

и записываем туда такие данные

[program:myproject]
command=/home/myprojectenv/bin/gunicorn myproject.wsgi:application -c /home/myprojectenv/myproject/myproject/gunicorn.conf.py
directory=/home/myprojectenv/myproject
user=nobody
autorestart=true
redirect_stderr=true

 

Запускаем проект через supervisor

supervisorctl restart myproject

В браузере набираем 11.22.33.44:8000 и убеждаемся, что все ок.

Дополнительный тест. Можно также перезагрузить сервер

shutdown -r now

и убедиться, что наш проекта на Django сам автоматом встал и заработал при помощи supervisor.

При использовании Supervisor необходимо использовать его подпроцесс управления supervisorctl. Остальные основные команды supervisor

  • supervisorctl start myproject — запуск процесса;
  • supervisorctl reread — перезапуск системы;
  • supervisorctl update — обновить систему;
  • supervisorctl status myproject — узнать статус процесса;
  • supervisorctl remove myproject — удалить процесс.

 

Возможные ошибки использования Supervisor и Gunicorn

Ошибки в файлах конфигурации

Это с большей вероятностью, потому что конфигурационных файлов 2 и нужно, чтобы они были настроены слажено без ошибок. Напомним, что они у нас находятся по путям:

  • Файл конфигурации Gunicorn в пределах текущего проекта /home/myprojectenv/myproject/myproject/gunicorn.conf.py
  • Файл конфигурации проекта в виде управляемого процесса внутри Supervisor /etc/supervisor/conf.d/myproject.conf

 

Ошибка запуска из-за занятости стандартного порта Supervisor

Обычно, эта ошибка выглядит так, при запуске команды запуска supervisorctl start myproject

cloudApp: ERROR (spawn error)

или так, при запуске команды поиска ошибок supervisord -n

Error: Another program is already listening on a port that one of our HTTP servers is configured to use.  Shut this program down first before starting supervisord

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

Первый. Выводим весь список процессов Supervisor и убиваем нужный по PID(в списке он будет после первого)

ps -ef | grep supervisord
sudo kill -9 PID_OUR_PROJECT

или

ps -ef | grep supervisord
kill -s SIGTERM PID_OUR_PROJECT

 

Второй. Убиваем сам supervisord

sudo pkill supervisord

 

Третий. Удаляем файл supervisor.sock и запускаем supervisor обратно

sudo unlink /run/supervisor.sock
sudo /etc/init.d/supervisor start

Теперь перезапускаем проект

supervisorctl start cloudApp
Ошибка ERROR (no such process) при запуске нового процесса

Данная ошибка появляется, когда мы создали новый проект, но он не обновился в системе Supervisot и для решения этой проблемы нам нужно перезаписать все процессы и перезагрузить supervisorctl

supervisorctl reread
supervisorctl reload

 

Если не удается идентифицировать ошибку

Если проблему трудно найти или идентифицировать, то будет полезной использовать команду

supervisord -n

который выведет весь список ошибок в файлах или сервисах, которые мешают запускаться процессу Supervisor.

 

Использованные материалы:

  1. Django + Python3 + Nginx + Gunicorn + DO;
  2. Setting up Django with Nginx, Gunicorn, virtualenv, supervisor and PostgreSQL