Tutorial

Настройка Django с Postgres, Nginx и Gunicorn в Ubuntu 18.04

Published on January 7, 2020
Русский
Настройка Django с Postgres, Nginx и Gunicorn в Ubuntu 18.04

Введение

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

В этом руководстве мы покажем, как установить и настроить определенные компоненты Ubuntu 18.04 для поддержки и обслуживания приложений Django. Вначале мы создадим базу данных PostgreSQL вместо того, чтобы использовать базу данных по умолчанию SQLite. Мы настроим сервер приложений Gunicorn для взаимодействия с нашими приложениями. Затем мы настроим Nginx для работы в качестве обратного прокси-сервера Gunicorn, что даст нам доступ к функциям безопасности и повышения производительности для обслуживания наших приложений.

Предварительные требования и цели

Для прохождения этого обучающего модуля вам потребуется новый экземпляр сервера Ubuntu 18.04 с базовым брандмауэром и пользователем с привилегиями sudo и без привилегий root. Чтобы узнать, как настроить такой сервер, воспользуйтесь нашим модулем Руководство по начальной настройке сервера.

Мы будем устанавливать Django в виртуальной среде. Установка Django в отдельную среду проекта позволит отдельно обрабатывать проекты и их требования.

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

Давайте приступим.

Установка пакетов из хранилищ Ubuntu

Чтобы начать данную процедуру нужно загрузить и установить все необходимые нам элементы из хранилищ Ubuntu. Для установки дополнительных компонентов мы немного позднее используем диспетчер пакетов Python pip.

Нам нужно обновить локальный индекс пакетов apt, а затем загрузить и установить пакеты. Конкретный состав устанавливаемых пакетов зависит от того, какая версия Python будет использоваться в вашем проекте.

Если вы используете Django с Python 3, введите:

  1. sudo apt update
  2. sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

Версия Django 1.11 — последняя версия Django с поддержкой Python 2. Если вы создаете новый проект, мы настоятельно рекомендуем использовать Python 3. Если вам необходимо использовать Python 2, введите:

  1. sudo apt update
  2. sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

Эта команда устанавливает pip, файлы разработки Python для последующего построения сервера Gunicorn, СУБД Postgres и необходимые для взаимодействия с ней библиотеки, а также веб-сервер Nginx.

Создание базы данных и пользователя PostgreSQL

Вначале мы создадим базу данных и пользователя базы данных для нашего приложения Django.

По умолчанию Postgres использует для локальных соединений схему аутентификации «peer authentication». Это означает, что если имя пользователя операционной системы совпадает с действительным именем пользователя Postgres, этот пользователь может войти без дополнительной аутентификации.

Во время установки Postgres был создан пользователь операционной системы с именем postgres, соответствующий пользователю postgres базы данных PostgreSQL, имеющему права администратора. Этот пользователь нам потребуется для выполнения административных задач. Мы можем использовать sudo и передать это имя пользователя с опцией -u.

Выполните вход в интерактивный сеанс Postgres, введя следующую команду:

  1. sudo -u postgres psql

Вы увидите диалог PostgreSQL, где можно будет задать наши требования.

Вначале создайте базу данных для своего проекта:

  1. CREATE DATABASE myproject;

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

Затем создайте пользователя базы данных для нашего проекта. Обязательно выберите безопасный пароль:

  1. CREATE USER myprojectuser WITH PASSWORD 'password';

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

Мы зададим кодировку по умолчанию UTF-8, чего и ожидает Django. Также мы зададим схему изоляции транзакций по умолчанию «read committed», которая будет блокировать чтение со стороны неподтвержденных транзакций. В заключение мы зададим часовой пояс. По умолчанию наши проекты Django настроены на использование времени по Гринвичу (UTC). Все эти рекомендации взяты из проекта Django:

  1. ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
  2. ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
  3. ALTER ROLE myprojectuser SET timezone TO 'UTC';

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

  1. GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

Завершив настройку, закройте диалог PostgreSQL с помощью следующей команды:

  1. \q

Теперь настройка Postgres завершена, и Django может подключаться к базе данных и управлять своей информацией в базе данных.

Создание виртуальной среды Python для вашего проекта

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

Для этого нам потребуется доступ к команде virtualenv. Для установки мы можем использовать pip.

Если вы используете Python 3, обновите pip и установите пакет с помощью следующей команды:

  1. sudo -H pip3 install --upgrade pip
  2. sudo -H pip3 install virtualenv

Если вы используете Python 2, обновите pip и установите пакет с помощью следующей команды:

  1. sudo -H pip install --upgrade pip
  2. sudo -H pip install virtualenv

После установки virtualenv мы можем начать формирование нашего проекта. Создайте каталог для файлов нашего проекта и перейдите в этот каталог:

  1. mkdir ~/myprojectdir
  2. cd ~/myprojectdir

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

  1. virtualenv myprojectenv

Эта команда создаст каталог myprojectenv в каталоге myprojectdir. В этот каталог будут установлены локальная версия Python и локальная версия pip. Мы можем использовать эту команду для установки и настройки изолированной среды Python для нашего проекта.

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

  1. source myprojectenv/bin/activate

Командная строка изменится, показывая, что теперь вы работаете в виртуальной среде Python. Она будет выглядеть примерно следующим образом: (myprojectenv)user@host:~/myprojectdir$.

После запуска виртуальной среды установите Django, Gunicorn и адаптер psycopg2 PostgreSQL с помощью локального экземпляра pip:

Примечание. Если виртуальная среда активна (когда перед командной строкой стоит (myprojectenv)), необходимо использовать pip вместо pip3, даже если вы используете Python 3. Копия инструмента в виртуальной среде всегда имеет имя pip вне зависимости от версии Python.

  1. pip install django gunicorn psycopg2-binary

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

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

Установив компоненты Python, мы можем создать реальные файлы проекта Django.

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

Поскольку у нас уже есть каталог проекта, мы укажем Django установить файлы в него. В этом каталоге будет создан каталог второго уровня с фактическим кодом (это нормально) и размещен скрипт управления. Здесь мы явно определяем каталог, а не даем Django принимать решения относительно текущего каталога:

  1. django-admin.py startproject myproject ~/myprojectdir

Сейчас каталог вашего проекта (в нашем случае ~/myprojectdir) должен содержать следующее:

  • ~/myprojectdir/manage.py: скрипт управления проектами Django.
  • ~/myprojectdir/myproject/: пакет проекта Django. В нем должны содержаться файлы __init__.py, settings.py, urls.py и wsgi.py.
  • ~/myprojectdir/myprojectenv/: виртуальный каталог, которы мы создали до этого.

Изменение настроек проекта

Прежде всего, необходимо изменить настройки созданных файлов проекта. Откройте файл настроек в текстовом редакторе:

  1. nano ~/myprojectdir/myproject/settings.py

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

В квадратных скобках перечислите IP-адреса или доменные имена, связанные с вашим сервером Django. Каждый элемент должен быть указан в кавычках, отдельные записи должны быть разделены запятой. Если вы хотите включить в запрос весь домен и любые субдомены, добавьте точку перед началом записи. В следующем фрагменте кода для демонстрации в строках комментариев приведено несколько примеров:

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

~/myprojectdir/myproject/settings.py
. . .
# The simplest case: just add the domain name(s) and IP addresses of your Django server
# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
# To respond to 'example.com' and any subdomains, start the domain with a dot
# ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']

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

Измените настройки, указав параметры базы данных PostgreSQL. Мы укажем Django использовать адаптер psycopg2, который мы установили вместе с pip. Нам нужно указать имя базы данных, имя пользователя базы данных, пароль пользователя базы данных, и указать, что база данных расположена на локальном компьютере. Вы можете оставить для параметра PORT пустую строку:

~/myprojectdir/myproject/settings.py
. . .

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

. . .

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

~/myprojectdir/myproject/settings.py
. . .

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

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

Завершение начальной настройки проекта

Теперь мы можем перенести начальную схему базы данных для нашей базы данных PostgreSQL, используя скрипт управления:

  1. ~/myprojectdir/manage.py makemigrations
  2. ~/myprojectdir/manage.py migrate

Создайте административного пользователя проекта с помощью следующей команды:

  1. ~/myprojectdir/manage.py createsuperuser

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

Мы можем собрать весь статичный контент в заданном каталоге с помощью следующей команды:

  1. ~/myprojectdir/manage.py collectstatic

Данную операцию нужно будет подтвердить. Статичные файлы будут помещены в каталог static в каталоге вашего проекта.

Если вы следовали указаниям модуля по начальной настройке сервера, ваш сервер должен защищать брандмауэр UFW. Чтобы протестировать сервер разработки, необходимо разрешить доступ к порту, который мы будем использовать.

Создайте исключение для порта 8000 с помощью следующей команды:

  1. sudo ufw allow 8000

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

  1. ~/myprojectdir/manage.py runserver 0.0.0.0:8000

Откройте в браузере доменное имя или IP-адрес вашего сервера с суффиксом :8000:

http://server_domain_or_IP:8000

Вы увидите страницу индекса Django по умолчанию:

Страница индекса Django

Если вы добавите /admin в конце URL в панели адреса, вам будет предложено ввести имя пользователя и пароль администратора, созданные с помощью команды createsuperuser:

Вход в панель администратора Django

После аутентификации вы получите доступ к интерфейсу администрирования Django по умолчанию:

Интерфейс администрирования Django

Завершив изучение, нажмите CTRL+C в окне терминала, чтобы завершить работу сервера разработки.

Тестирование способности Gunicorn обслуживать проект

Перед выходом из виртуальной среды нужно протестировать способность Gunicorn обслуживать приложение. Для этого нам нужно войти в каталог нашего проекта и использовать gunicorn для загрузки модуля WSGI проекта:

  1. cd ~/myprojectdir
  2. gunicorn --bind 0.0.0.0:8000 myproject.wsgi

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

Примечание. В интерфейсе администратора не будут применяться в стили, поскольку Gunicorn неизвестно, как находить требуемый статичный контент CSS.

Мы передали модуль в Gunicorn, указав относительный путь к файлу Django wsgi.py, который представляет собой точку входа в наше приложение. Для этого мы использовали синтаксис модуля Python. В этом файле определена функция application, которая используется для взаимодействия с приложением. Дополнительную информацию о спецификации WSGI можно найти здесь.

После завершения тестирования нажмите CTRL+C в окне терминала, чтобы остановить работу Gunicorn.

Мы завершили настройку нашего приложения Django. Теперь мы можем выйти из виртуальной среды с помощью следующей команды:

  1. deactivate

Индикатор виртуальной среды будет убран из командной строки.

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

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

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

Создайте и откройте файл сокета systemd для Gunicorn с привилегиями sudo:

  1. sudo nano /etc/systemd/system/gunicorn.socket

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

/etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

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

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

  1. sudo nano /etc/systemd/system/gunicorn.service

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

/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

Теперь откроем раздел [Service]. Здесь указываются пользователь и группа, от имени которых мы хотим запустить данный процесс. Мы сделаем владельцем процесса учетную запись обычного пользователя, поскольку этот пользователь является владельцем всех соответствующих файлов. Групповым владельцем мы сделаем группу www-data, чтобы Nginx мог легко взаимодействовать с Gunicorn.

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

/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

Наконец, добавим раздел [Install]. Это покажет systemd, куда привязывать эту службу, если мы активируем ее запуск при загрузке. Нам нужно, чтобы эта служба запускалась во время работы обычной многопользовательской системы:

/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Теперь служебный файл systemd готов. Сохраните и закройте его.

Теперь мы можем запустить и активировать сокет Gunicorn. Файл сокета /run/gunicorn.sock будет создан сейчас и будет создаваться при загрузке. При подключении к этому сокету systemd автоматически запустит gunicorn.service для его обработки:

  1. sudo systemctl start gunicorn.socket
  2. sudo systemctl enable gunicorn.socket

Успешность операции можно подтвердить, проверив файл сокета.

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

Проверьте состояние процесса, чтобы узнать, удалось ли его запустить:

  1. sudo systemctl status gunicorn.socket

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

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

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

  1. sudo journalctl -u gunicorn.socket

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

Тестирование активации сокета

Если вы запустили только gunicorn.socket, служба gunicorn.service не будет активна в связи с отсутствием подключений к совету. Для проверки можно ввести следующую команду:

  1. sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: inactive (dead)

Чтобы протестировать механизм активации сокета, установим соединение с сокетом через curl с помощью следующей команды:

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

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

  1. sudo systemctl status gunicorn
Output
● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Mon 2018-07-09 20:00:40 UTC; 4s ago Main PID: 1157 (gunicorn) Tasks: 4 (limit: 1153) CGroup: /system.slice/gunicorn.service ├─1157 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1178 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application ├─1180 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application └─1181 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application Jul 09 20:00:40 django1 systemd[1]: Started gunicorn daemon. Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Starting gunicorn 19.9.0 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Listening at: unix:/run/gunicorn.sock (1157) Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Using worker: sync Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1178] [INFO] Booting worker with pid: 1178 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1180] [INFO] Booting worker with pid: 1180 Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1181] [INFO] Booting worker with pid: 1181 Jul 09 20:00:41 django1 gunicorn[1157]: - - [09/Jul/2018:20:00:41 +0000] "GET / HTTP/1.1" 200 16348 "-" "curl/7.58.0"

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

  1. sudo journalctl -u gunicorn

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

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart gunicorn

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

Настройка Nginx как прокси для Gunicorn

Мы настроили Gunicorn, и теперь нам нужно настроить Nginx для передачи трафика в процесс.

Для начала нужно создать и открыть новый серверный блок в каталоге Nginx sites-available:

  1. sudo nano /etc/nginx/sites-available/myproject

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

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name server_domain_or_IP;
}

Затем мы укажем Nginx игнорировать любые проблемы при поиске favicon. Также мы укажем, где можно найти статичные ресурсы, собранные нами в каталоге ~/myprojectdir/static. Все эти строки имеют стандартный префикс URI «/static», так что мы можем создать блок location для соответствия этим запросам:

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }
}

В заключение мы создадим блок location / {} для соответствия всем другим запросам. В этот блок мы включим стандартный файл proxy_params, входящий в комплект установки Nginx, и тогда трафик будет передаваться напрямую на сокет Gunicorn:

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Сохраните файл и закройте его после завершения. Теперь мы можем активировать файл, привязав его к каталогу sites-enabled:

  1. sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

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

  1. sudo nginx -t

Если ошибок не будет найдено, перезапустите Nginx с помощью следующей команды:

  1. sudo systemctl restart nginx

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

  1. sudo ufw delete allow 8000
  2. sudo ufw allow 'Nginx Full'

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

Примечание. После настройки Nginx необходимо защитить трафик на сервер с помощью SSL/TLS. Это важно, поскольку в противном случае вся информация, включая пароли, будет отправляться через сеть в простом текстовом формате.

Если у вас имеется доменное имя, проще всего будет использовать Let’s Encrypt для получения сертификата SSL для защиты вашего трафика. Следуйте указаниям этого руководства, чтобы настроить Let’s Encrypt с Nginx в Ubuntu 18.04. Следуйте процедуре, используя серверный блок Nginx, созданный нами в этом обучающем модуле.

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

Диагностика и устранение неисправностей Nginx и Gunicorn

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

Nginx показывает страницу по умолчанию, а не приложение Django

Если Nginx показывает страницу по умолчанию, а не выводит ваше приложение через прокси, это обычно означает, что вам нужно изменить параметр server_name в файле /etc/nginx/sites-available/myproject, чтобы он указывал на IP-адрес или доменное имя вашего сервера.

Nginx использует server_name, чтобы определять, какой серверный блок использовать для ответа на запросы. Если вы увидите страницу Nginx по умолчанию, это будет означать, что Nginx не может найти явное соответствие запросу в серверном блоке и выводит блок по умолчанию, заданный в /etc/nginx/sites-available/default.

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

Nginx выводит ошибку 502 Bad Gateway вместо приложения Django

Ошибка 502 означает, что Nginx не может выступать в качестве прокси для запроса. Ошибка 502 может сигнализировать о разнообразных проблемах конфигурации, поэтому для диагностики и устранения неисправности потребуется больше информации.

В первую очередь эту информацию следует искать в журналах ошибок Nginx. Обычно это указывает, какие условия вызвали проблемы во время прокси-обработки. Изучите журналы ошибок Nginx с помощью следующей команды:

  1. sudo tail -F /var/log/nginx/error.log

Теперь выполните в браузере еще один запрос, чтобы получить свежее сообщение об ошибке (попробуйте обновить страницу). В журнал будет записано свежее сообщение об ошибке. Если вы изучите его, это поможет идентифицировать проблему.

Возможно вы увидите сообщение следующего вида:

connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

Это означает, что Nginx не удалось найти файл gunicorn.sock в указанном месте. Вы должны сравнить расположение proxy_pass, определенное в файле etc/nginx/sites-available/myproject, с фактическим расположением файла gunicorn.sock, сгенерированным блоком systemd gunicorn.socket.

Если вы не можете найти файл gunicorn.sock в каталоге /run, это означает, что файл сокета systemd не смог его создать. Вернитесь к разделу проверки файла сокета Gunicorn и выполните процедуру диагностики и устранения неисправностей Gunicorn.

connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

Это означает, что Nginx не удалось подключиться к сокету Gunicorn из-за проблем с правами доступа. Это может произойти, если процедуру выполнять с привилегиями root, а не с привилегиями sudo. Хотя systemd может создать файл сокета Gunicorn, Nginx не может получить к нему доступ.

Это может произойти из-за ограничения прав доступа в любом месте между корневым каталогом (/) и файлом gunicorn.sock. Чтобы увидеть права доступа и владельцев файла сокета и всех его родительских каталогов, нужно ввести абсолютный путь файла сокета как параметр команды namei:

  1. namei -l /run/gunicorn.sock
Output
f: /run/gunicorn.sock drwxr-xr-x root root / drwxr-xr-x root root run srw-rw-rw- root root gunicorn.sock

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

В приведенном выше примере для файла сокета и каждого из каталогов пути к файлу сокета установлены всеобщие права доступа на чтение и исполнение (запись в столбце разрешений каталогов заканчивается на r-x, а не на ---). Процесс Nginx должен успешно получить доступ к сокету.

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

Django выводит ошибку: «could not connect to server: Connection refused»

При попытке доступа к частям приложения через браузер Django может вывести сообщение следующего вида:

OperationalError at /admin/login/
could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

Это означает, что Django не может подключиться к базе данных Postgres. Убедиться в нормальной работе экземпляра Postgres с помощью следующей команды:

  1. sudo systemctl status postgresql

Если он работает некорректно, вы можете запустить его и включить автоматический запуск при загрузке (если эта настройка еще не задана) с помощью следующей команды:

  1. sudo systemctl start postgresql
  2. sudo systemctl enable postgresql

Если проблемы не исчезнут, проверьте правильность настроек базы данных, заданных в файле ~/myprojectdir/myproject/settings.py.

Дополнительная диагностика и устранение неисправностей

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

Следующие журналы могут быть полезными:

  • Проверьте журналы процессов Nginx с помощью команды: sudo journalctl -u nginx
  • Проверьте журналы доступа Nginx с помощью команды: sudo less /var/log/nginx/access.log
  • Проверьте журналы ошибок Nginx с помощью команды: sudo less /var/log/nginx/error.log
  • Проверьте журналы приложения Gunicorn с помощью команды: sudo journalctl -u gunicorn
  • Проверьте журналы сокета Gunicorn с помощью команды: sudo journalctl -u gunicorn.socket

При обновлении конфигурации или приложения вам может понадобиться перезапустить процессы для адаптации к изменениям.

Если вы обновите свое приложение Django, вы можете перезапустить процесс Gunicorn для адаптации к изменениям с помощью следующей команды:

  1. sudo systemctl restart gunicorn

Если вы измените файл сокета или служебные файлы Gunicorn, перезагрузите демона и перезапустите процесс с помощью следующей команды:

  1. sudo systemctl daemon-reload
  2. sudo systemctl restart gunicorn.socket gunicorn.service

Если вы измените конфигурацию серверного блока Nginx, протестируйте конфигурацию и Nginx с помощью следующей команды:

  1. sudo nginx -t && sudo systemctl restart nginx

Эти команды помогают адаптироваться к изменениям в случае изменения конфигурации.

Заключение

В этом руководстве мы создали и настроили проект Django в его собственной виртуальной среде. Мы настроили Gunicorn для трансляции запросов клиентов, чтобы Django мог их обрабатывать. Затем мы настроили Nginx в качестве обратного прокси-сервера для обработки клиентских соединений и вывода проектов, соответствующих запросам клиентов.

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

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
7 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Добрый день, а в команде:

gunicorn --bind 0.0.0.0:8000 myproject.wsgi

путь до модуля wsgi может состоять не из одной папки? В моей задаче фактически команда имеет вид:

gunicorn 32-crud.stocks_products.wsgi:application --bind 0.0.0.0:8001

но почему-то при выполнении stocks_products не находится, в логе написано ModuleNotFoundError: No module named ‘stocks_products’, хотя папка совершенно точно лежит внутри 32-crud. В связи с этим вопрос, здесь ограничение на глубину вложенности, или какой-то специальный синтаксис надо использовать? Или еще что-то, что я даже не могу себе представить? :)

That’s an incredible walkthrough, thanks!

It can be only me, but when I set my /static/ location as it is described here, I can see /static/static/ path requests in my nginx log.

However, if I put it like this:

location /static/ {
    root /my-project-dir;
}

I have no problems with my static content, assuming that I have static dir in my-project-dir and all permissions are correct

Инструкция очень помогла, впервые вижу такую точную пошаговую статью, сэкономила мне кучу времени, большое спасибо автору!

При выполнении команды sudo systemctl start gunicorn.socket возникает ошибка System has not been booted with systemd as init system (PID 1). Can’t operate. Failed to connect to bus: Host is down

This article really helps me a lot! Thanks!)

Примечание. В интерфейсе администратора не будут применяться в стили, поскольку Gunicorn неизвестно, как находить требуемый статичный контент CSS.

Друзья, каким образом это можно исправить?

Пытаюсь установить Django 3.0.4 на сервере Ubuntu Server 18.04 LTS (HVM), 64-bit (x86) При выполнении команды ~/myprojectdir/manage.py makemigrations выдает No changes detected. Пробовал указывать в INSTALLED_APPS название проекта, нo не помогло.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel