Настройка Django+PosgtreSQL+Gunicorn

Опубликовано:

Мы установили Python 3.7

Настроили виртуальное окружение

Установили и настроили Postgresql

Далее внутри виртуального окружения ставим необходимый пакет программ

Ставим Django и Gunicorn внутри виртуального окружения.

Gunicorn будет выступать в качестве HTTP сервера для сайта.

(dj-project) $ pip3 install django gunicorn

Смотрим какие при этом зависимости установились

(dj-project) $ pip3 freeze
Django==2.2.4

Создаём Django-проект

(dj-project) $ django-admin.py startproject myproject

Сохраняем зависимости

(dj-project) $ pip freeze > myproject/requirements.txt 

Настройка проекта

После этого нужно настроить проект. Откройте файл settings.py в текстовом редакторе:

 $ mcedit  /var/www/myprojectdir/myproject/settings.py
Находим в файле директиву ALLOWED_HOSTS. Она содержит белый список адресов и доменов, которые могут подключаться к Django. Если входящий запрос содержит заголовок Host, который не включен в этот список, такой запрос будет сброшен. Это обеспечит дополнительный уровень безопасности Django.

Перечислите в квадратных скобках все заведомо безопасные для Django IP-адреса или домены. Каждый элемент нужно взять в одинарные кавычки. Все элементы списка разделяются запятыми. Чтобы добавить в список поддомены, поставьте перед доменным именем точку. В приведённом ниже фрагменте вы найдёте несколько закомментированных примеров того, как может выглядеть директива ALLOWED_HOSTS.
При DEBUG равном True и при выполнении тестов проверка отключена. Проверка обычно нужна только на боевом сервере.

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

Затем находим раздел настроек доступа к БД — DATABASES. Указваем имя БД, имя и пароль пользователя базы данных, а затем укажите, что база данных находится на локальном компьютере.

'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'django_db',
'USER' : 'user_name',
'PASSWORD' : 'password',
'HOST' : '127.0.0.1',
'PORT' : '5432',

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

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

В окружении проекта устанавливаем бэкэнд для PostgreSQL

(dj-project) $ pip install  psycopg2
 При ошибке Error: pg_config executable not found.  

Указываем путь до pg_config

PATH=$PATH:/usr/lib/postgresql/12/bin/

и устанавливаем пакет для разработки клиентских приложений и серверных расширений.

Выполнение миграций базы данных

Django обладает одним очень большим преимуществом — он имеет встроенную админку, что очень облегчает жизнь. Но чтобы она заработала, необходимо выполнить миграцию базы данных, то есть подготовить из моделей данных SQL запросы, которые сформируют структуру базу данных.

 cd ./myproject
(dj-project)python manage.py makemigrations
(dj-project)python manage.py migrate

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

(dj-project)python manage.py createsuperuser

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

(dj-project)python manage.py collectstatic

Подтвердите операцию. Теперь все статические файлы хранятся в каталоге static.

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

(dj-project)python manage.py runserver 0.0.0.0:8000 

Открываем в браузере доменное имя или IP-адрес и указываем порт :8000.

http://server_domain_or_IP:8000

На экране появится приветственная страница Django.

Добавьте /admin в конец адреса. Браузер запросит учётные данные администратора. Заполните поля, указав имя и пароль только что созданной учётной записи администратора при помощи команды createsuperuser. После этого на экране появится интерфейс администратора.

Завершив проверку, останавливаем сервер разработки, нажав CTRL-C в окне терминала.

gunicorn --bind 0.0.0.0:8000 myproject.wsgi

Эта команда запустит Gunicorn в том же интерфейсе, в котором до этого работал сервер разработки Django. Вернемся и снова протестируем приложение.

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

Завершим проверку, останавливаем Gunicorn, нажав CTRL-C в окне терминала.

Создание системных сокетов и служебных файлов для Gunicorn

Мы проверили, что Gunicorn может взаимодействовать с нашим приложением Django, но мы должны реализовать более надежный способ запуска и остановки сервера приложений. Для этого мы создадим файлы службы systemd и сокетов.

Сокет Gunicorn будет создан при загрузке и будет прослушивать соединения. Когда происходит соединение, systemd автоматически запускает процесс Gunicorn для обработки соединения.

Создадим файла сокета systemd для Gunicorn:

sudo mcedit /etc/systemd/system/gunicorn.socket

Внутри мы создадим
[Unit] раздел для описания сокета,
[Socket] раздел для определения местоположения сокета и
[Install] раздел, чтобы убедиться, что сокет создан в нужное время:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target

Далее создаем служебный файл systemd для Gunicorn. Имя файла службы должно соответствовать имени файла сокета, за исключением расширения:

sudo mcedit  /etc/systemd/system/gunicorn.service

Начните с [Unit]раздела, который используется для указания метаданных и зависимостей. Мы поместим здесь описание нашего сервиса и сообщим системе инициализации запускать его только после того, как цель сети достигнута. Поскольку наш сервис опирается на сокет из файла сокета, нам нужно включить Requires директиву, чтобы указать эту связь:

[Unit] раздел, который используется для указания метаданных и зависимостей. Мы поместим здесь описание нашего сервиса и сообщить системе инициализации запускать его только после того, как цель сети достигнута. Поскольку наш сервис запускается через сокет, нам нужно включить Requires директиву, чтобы указать эту связь:

[Service] раздел. Здесь мы определим пользователя и группу, под которой мы хотим работать. Предоставим доступ группе www-data, чтобы Nginx мог легко общаться с Gunicorn.

Затем укажем рабочий каталог и команду для запуска сервиса. В этом случае нам нужно будет указать полный путь к исполняемому файлу Gunicorn, который устанавливается в нашей виртуальной среде. Свяжем процесс с сокетом Unix, который мы создали в /run каталоге, чтобы процесс мог взаимодействовать с Nginx. Записываем все данные в стандартный вывод, чтобы journald процесс мог собирать журналы Gunicorn. Также можем указать любые дополнительные настройки Gunicorn здесь. Например, мы указали 3 рабочих процесса:

[Install] раздел. Он указывает systemd, с чем связать этот сервис, если мы включим его при загрузке. Мы хотим, чтобы эта служба запускалась и работала, когда обычная многопользовательская система:

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myprojectdir/myproject/
ExecStart=/var/www/myprojectdir/venv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application
[Install]
WantedBy=multi-user.target

Теперь запустим и включим сокет Gunicorn. Следующие команды создадут файл сокета /run/gunicorn.sock сейчас и при следующей загрузке системы Когда будет установлено соединение с этим сокетом, systemd автоматически начнет обрабатывать его gunicorn.service :

sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

Для того чтобы проверить , что операция прошла успешно, проверив наличие файла сокета.

Проверка на наличие файла сокета Gunicorn

Проверьте состояние процесса:

 sudo systemctl status gunicorn.socket

Далее, проверьте наличие gunicorn.sock файла в /runкаталоге:

file /run/gunicorn.sock
Output
/run/gunicorn.sock: socket

Если в результате работы команды systemctl status произошла ошибка, или если вы не нашли gunicorn.sock файл в каталоге, это означает, что сокет Gunicorn не был создан правильно. Проверьте логи сокета Gunicorn, набрав:

 sudo journalctl -u gunicorn.socket

Еще раз посмотрите настройки в файле /etc/systemd/system/gunicorn.socket и исправить проблемы, прежде чем продолжить.

Для проверки работы и активации сокета, подключимся curl через сокет :

curl --unix-socket /run/gunicorn.sock localhost

В консоли должно быть отображено содержание HTML страницы. Это указывает на то, что Gunicorn был запущен и смог обработать ваше приложение Django.

Проверяем что служба Gunicorn работает:

sudo systemctl status gunicorn

Если возникли проблемы после curl или systemctl status, проверяем в журналах дополнительную информацию:

 sudo journalctl -u gunicorn

Проверяем и при необходимости вносим изменения /etc/systemd/system/gunicorn.service. После внесения изменении файл /etc/systemd/system/gunicorn.service, необходимо перезагрузите демон, чтобы перечитать конфиг сервиса и перезапустить процесс Gunicorn:

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

Настроить Nginx на Proxy Pass для Gunicorn

Теперь, когда Gunicorn настроен, нам нужно настроить Nginx.

Создаем нового виртуальный сервер Nginx :

sudo mcedit /etc/nginx/sites-available/myproject

В блоке server. Указываем что будем прослушивать порт 80 и он должен отвечать на доменное имя или IP-адрес нашего сервера:

server {
    listen 80;
    server_name server_domain_or_IP;

    location /static/ {
        root /var/www/myprojectdir/myproject;
    }

    location = /favicon.ico {
        alias /var/www/myprojectdir/myproject/static/favicon.ico;
    }
    location = /favicon.ico { access_log off; log_not_found off; }

    location = /robots.txt {
        alias /var/www/myprojectdir/myproject/static/robots.txt;
    }
    location /media/ {
        root /var/www/myprojectdir/myproject/media;
    }
    # Взаимодействуем с Django-приложением через unix-сокет
    location / {
        include proxy_params;
        include     /etc/nginx/uwsgi_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

Проверим конфигурацию Nginx на наличие синтаксических ошибок:

 sudo nginx -t 

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

sudo systemctl restart nginx

Понравилась статья, расскажи о ней друзьям, нажми кнопку!