One place for hosting & domains

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


      Введение

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

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

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

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

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

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

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

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

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

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

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

      • sudo apt update
      • sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

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

      • sudo apt update
      • 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, введя следующую команду:

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

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

      • CREATE DATABASE myproject;

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

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

      • CREATE USER myprojectuser WITH PASSWORD 'password';

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

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

      • ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
      • ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
      • ALTER ROLE myprojectuser SET timezone TO 'UTC';

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

      • GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

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

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

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

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

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

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

      • sudo -H pip3 install --upgrade pip
      • sudo -H pip3 install virtualenv

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

      • sudo -H pip install --upgrade pip
      • sudo -H pip install virtualenv

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

      • mkdir ~/myprojectdir
      • cd ~/myprojectdir

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

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

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

      • source myprojectenv/bin/activate

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

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

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

      • pip install django gunicorn psycopg2-binary

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

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

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

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

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

      • django-admin.py startproject myproject ~/myprojectdir

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

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

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

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

      • 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, используя скрипт управления:

      • ~/myprojectdir/manage.py makemigrations
      • ~/myprojectdir/manage.py migrate

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

      • ~/myprojectdir/manage.py createsuperuser

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

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

      • ~/myprojectdir/manage.py collectstatic

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

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

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

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

      • ~/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 проекта:

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

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

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

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

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

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

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

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

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

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

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

      • 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 в текстовом редакторе. Имя файла службы должно соответствовать имени файла сокета за исключением расширения:

      • 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 для его обработки:

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

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

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

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

      • sudo systemctl status gunicorn.socket

      Вы должны получить следующий вывод:

      Output

      ● gunicorn.socket - gunicorn socket Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese> Active: active (listening) since Fri 2020-06-26 17:53:10 UTC; 14s ago Triggers: ● gunicorn.service Listen: /run/gunicorn.sock (Stream) Tasks: 0 (limit: 1137) Memory: 0B CGroup: /system.slice/gunicorn.socket

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

      Output

      /run/gunicorn.sock: socket

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

      • sudo journalctl -u gunicorn.socket

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

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

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

      • sudo systemctl status gunicorn

      Output

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

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

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

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

      • sudo systemctl status gunicorn

      Output

      ● gunicorn.service - gunicorn daemon Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled) Active: active (running) since Fri 2020-06-26 18:52:21 UTC; 2s ago TriggeredBy: ● gunicorn.socket Main PID: 22914 (gunicorn) Tasks: 4 (limit: 1137) Memory: 89.1M CGroup: /system.slice/gunicorn.service ├─22914 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22927 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> ├─22928 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> └─22929 /home/sammy/myprojectdir/myprojectenv/bin/python /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunico> Jun 26 18:52:21 django-tutorial systemd[1]: Started gunicorn daemon. Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Starting gunicorn 20.0.4 Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Listening at: unix:/run/gunicorn.sock (22914) Jun 26 18:52:21 django-tutorial gunicorn[22914]: [2020-06-26 18:52:21 +0000] [22914] [INFO] Using worker: sync Jun 26 18:52:21 django-tutorial gunicorn[22927]: [2020-06-26 18:52:21 +0000] [22927] [INFO] Booting worker with pid: 22927 Jun 26 18:52:21 django-tutorial gunicorn[22928]: [2020-06-26 18:52:21 +0000] [22928] [INFO] Booting worker with pid: 22928 Jun 26 18:52:21 django-tutorial gunicorn[22929]: [2020-06-26 18:52:21 +0000] [22929] [INFO] Booting worker with pid: 22929

      Если результаты выводов команд 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 как прокси для Gunicorn

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

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

      • 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:

      • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

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

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

      • sudo systemctl restart nginx

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

      • sudo ufw delete allow 8000
      • sudo ufw allow 'Nginx Full'

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

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

      Если у вас имеется доменное имя, проще всего будет использовать Let’s Encrypt для получения сертификата SSL для защиты вашего трафика. Следуйте указаниям этого руководства, чтобы настроить Let’s Encrypt с Nginx в Ubuntu 20.04. Следуйте процедуре, используя серверный блок 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 с помощью следующей команды:

      • 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:

      • 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 с помощью следующей команды:

      • sudo systemctl status postgresql

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

      • sudo systemctl start postgresql
      • 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 для адаптации к изменениям с помощью следующей команды:

      • sudo systemctl restart gunicorn

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

      • sudo systemctl daemon-reload
      • sudo systemctl restart gunicorn.socket gunicorn.service

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

      • sudo nginx -t && sudo systemctl restart nginx

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

      Заключение

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

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



      Source link