Tutorial
Настройка 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, введя следующую команду:
- sudo -u postgres psql
Вы увидите диалог 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 с помощью следующей команды:
- \q
Теперь настройка 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 с помощью следующей команды:
- virtualenv myprojectenv
Эта команда создаст каталог 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 в качестве прокси-сервера.
. . .
# 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
пустую строку:
. . .
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
. . .
Затем перейдите в конец файла и добавьте параметр, указывающий, где следует разместить статичные файлы. Это необходимо, чтобы Nginx мог обрабатывать запросы для этих элементов. Следующая строка дает указание Django поместить их в каталог с именем static
в базовом каталоге проекта:
. . .
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 с помощью следующей команды:
- sudo ufw allow 8000
Теперь вы можете протестировать ваш проект, запустив сервер разработки Django с помощью следующей команды:
- ~/myprojectdir/manage.py runserver 0.0.0.0:8000
Откройте в вашем браузере доменное имя или IP-адрес вашего сервера с суффиксом :8000
:
http://server_domain_or_IP:8000
Вы должны получить страницу индекса Django по умолчанию:
Если вы добавите /admin
в конце URL в адресной строке, вам будет предложено ввести имя пользователя и пароль администратора, созданные с помощью команды createsuperuser
:
После аутентификации вы получите доступ к интерфейсу администрирования 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. Теперь мы можем выйти из виртуальной среды с помощью следующей команды:
- deactivate
Индикатор виртуальной среды будет убран из командной строки.
Создание файлов сокета и служебных файлов systemd для Gunicorn
Мы убедились, что Gunicorn может взаимодействовать с нашим приложением Django, но теперь нам нужно реализовать более надежный способ запуска и остановки сервера приложений. Для этого мы создадим служебные файлы и файлы сокета systemd.
Сокет Gunicorn создается при загрузке и прослушивает подключения. При подключении systemd автоматически запускает процесс Gunicorn для обработки подключения.
Создайте и откройте файл сокета systemd для Gunicorn с привилегиями sudo
:
- sudo nano /etc/systemd/system/gunicorn.socket
В этом файле мы создадим раздел [Unit]
для описания сокета, раздел [Socket]
для определения расположения сокета и раздел [Install]
, чтобы обеспечить установку сокета в нужное время:
[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
, чтобы задать это отношение:
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
Теперь откроем раздел [Service]
. Здесь указываются пользователь и группа, от имени которых мы хотим запустить данный процесс. Мы сделаем владельцем процесса учетную запись обычного пользователя, поскольку этот пользователь является владельцем всех соответствующих файлов. Групповым владельцем мы сделаем группу www-data
, чтобы Nginx мог легко взаимодействовать с Gunicorn.
Затем мы составим карту рабочего каталога и зададим команду для запуска службы. В данном случае мы укажем полный путь к исполняемому файлу Gunicorn, установленному в нашей виртуальной среде. Мы привяжем процесс к сокету Unix, созданному в каталоге /run
, чтобы процесс мог взаимодействовать с Nginx. Мы будем регистрировать все данные на стандартном выводе, чтобы процесс journald
мог собирать журналы Gunicorn. Также здесь можно указать любые необязательные настройки Gunicorn. Например, в данном случае мы задали 3 рабочих процесса:
[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, куда привязывать эту службу, если мы активируем ее запуск при загрузке. Нам нужно, чтобы эта служба запускалась во время работы обычной многопользовательской системы:
[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
:
- 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
и устраните любые обнаруженные проблемы, прежде чем продолжить.
Тестирование активации сокета
Если вы запустили только 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-адрес нашего сервера:
server {
listen 80;
server_name server_domain_or_IP;
}
Затем мы укажем Nginx игнорировать любые проблемы при поиске favicon. Также мы укажем, где можно найти статичные ресурсы, собранные нами в каталоге ~/myprojectdir/static
. Все эти строки имеют стандартный префикс URI «/static», так что мы можем создать блок location для соответствия этим запросам:
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:
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 на ошибки синтаксиса:
- sudo nginx -t
Если ошибок не будет найдено, перезапустите 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
Outputf: /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 упрощает создание проектов и приложений, предоставляя множество стандартных элементов и позволяя сосредоточиться на уникальных. Используя описанную в этой статье процедуру, вы сможете легко обслуживать создаваемые приложения на одном сервере.