Установка и настройка Django 3 с Nginx, PostgreSQL, Gunicorn на Ubuntu 20


06 ноября 2020


Установка и настройка Django 3 с Nginx, PostgreSQL, Gunicorn WSGI на Ubuntu 20

В этой статье будет рассмотрена установка и настройка фреймворка Python Django 3, базы данных PostgreSQL, веб-сервера Nginx и WSGI сервера Gunicorn на Ubuntu 20. Подходы, которые используются в этой статье, подойдут для Django 2 и Ubuntu младших версий с небольшими отличиями. Различия между, версиями Django, тоже будут рассмотрены.

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

sudo apt update

Для того что бы Django 3 работал корректно ему нужен Python версии больше 3.6. Узнать версию Python, которая используется у вас по умолчанию можно так:

python3 --version

Проверка версии интерпретатора python на Ubuntu

Версия Python 3.8 по умолчанию идет вместе с Ubuntu 20.

Что бы вы смогли выполнить все операции ниже вам понадобится пользователь с правами sudo.

 

Установка пакетов

Что бы все приложения смогли работать вместе нам понадобится ряд пакетов, среди которых:

  • python3-pip - менеджер пакетов с помощью которого мы можем установить Django и другие пакеты;
  • python3-dev - нужен для работы с базой данных;
  • python3-venv - используется для изоляции пакетов, которые будут использоваться вашим проектом;
  • libpq-dev - нужен для работы с базой данных;
  • postgresql - база данных;
  • postgresql-contrib - расширение для работы с PostgreSQL;
  • nginx - веб сервер;
  • curl - программа для проверки работы протоколов.

Установить все пакеты мы можем с помощью следующей команды:

sudo apt install -y python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl python3-venv

По умолчанию у вас уже открыт 80 и 443 порт, и если вы откроете браузер или выполните следующую команду, то получите ответ Nginx т.к он слушает эти порты:

curl localhost

Проверка работы Nginx с curl на Ubuntu

Если это не так, то вы можете попробовать включить Nginx сами:

sudo systemctl enable --now nginx
systemctl status nginx

Проверка статуса сервиса Nginx на Ubuntu

Вы так же сможете посмотреть на работу nginx с другого компьютера указав IP адрес. IP адрес можно узнать с помощью следующей команды:

ip a

Просмотр IP адреса сервера Ubuntu

Проверка работы Nginx на Ubuntu

Если вы не можете открыть сайт используя свой ip адрес, то можно попробовать открыть порты в фаерволле:

sudo ufw allow http
sudo ufw allow https

 

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

С базой данных будет работать Django. Что бы это было возможно мы должны создать базу данных и ее пользователя.

При установке PostgreSQL автоматически создается пользователь postgres имеющий все права для управления сервером баз данных. С помощью его мы создадим пользователя и дадим права на базу. psql - это команда, которая позволяет подключаться к серверу базы данных локально:

sudo -u postgres psql

Подключение к PostgreSQL на Ubuntu 20

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

CREATE DATABASE fixmypc_database;

Создание базы PostgreSQL на Ubuntu 20

Создадим пользователя базы данных и дадим ему пароль. В моем случае пользователь 'fixmypc_database_user', а пароль 'password':

CREATE USER fixmypc_database_user WITH PASSWORD 'password';

Создание пользователя PostgreSQL с паролем на Ubuntu 20

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

  • client_encoding - использование кодировки 'utf8', которая является стандартом для Linux, веб-серверов и т.д;
  • default_transaction_isolation - режим изоляции транзакций. read committed - позволяет читать только те данные из таблицы, которые в данный момент не изменяются. Если данные изменяются, то вы будете ждать завершения их изменения;
  • timezone - часовая зона UTC.

В командах используется пользователь 'fixmypc_database_user'. Если вы создавали другого пользователя - вам нужно изменить эту часть в строках ниже:

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

Изменение кодировки PostgreSQL и часовой зоны на Ubuntu 20

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

GRANT ALL PRIVILEGES ON DATABASE fixmypc_database TO fixmypc_database_user;

Выдача прав на базу PostgreSQL на Ubuntu 20

Настройки базы завершены.  Выйдем из консоли:

\q

Выход из настройки PostgreSQL на Ubuntu 20

 

Создание виртуального окружения и работа с pip

Виртуальное окружение позволяет корректно хранить и управлять версиями пакетов, которые мы будем устанавливать с помощью pip (python3-pip). Этот пакет устанавливается отдельно. Что бы создать виртуальное окружение вы должны определиться с местом где будет храниться основная часть вашего Django сайта. В моем случае это будет корень Ubuntu '/', а папка будет называться fixmypc_folder. Я рекомендую запомнить название и путь, так как в дальнейшем все эти настройки еще понадобятся.

Создадим папку:

sudo mkdir /fixmypc_folder

Создание директории на Ubuntu 20

Перейдем в папку:

cd /fixmypc_folder

Мое окружение будет называться 'env' и это имя тоже понадобится для дальнейших настроек:

sudo python3 -m venv env
ls

Создание виртуального окружения Python на Ubuntu 20

Далее мы можем активировать виртуальное окружение:

source env/bin/activate

Активация виртуального окружения Python на Ubuntu 20

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

Далее мы установим пакеты, которые понадобятся для работы Django:

  • django - фреймворк, который мы используем;
  • gunicorn - WSGI сервер;
  • psycopg2-binary - библиотека для подключения к PostgreSQL.
sudo pip3 install django gunicorn psycopg2-binary

Установка django gunicorn psycopg2-binary на Ubuntu 20

 

Создание проекта Django и его настройка c settings.py

После того как вы установили нужные пакеты через pip нужно создать проект. В случае Django, создание проекта, это просто копирование шаблонных файлов объединенное в одну команду.

Проекту тоже нужно дать имя. В моем случае это будет 'fixmypc_project':

sudo django-admin startproject fixmypc_project

Теперь я имею следующую структуру папок, где проект и виртуальное окружение находятся на одном уровне:

Структура папок для настройки Django и Nginx на Ubuntu 20

По умолчанию в Django установлены настройки, которые разрешают просмотр  веб-сайта только локально (localhost/127.0.0.1). Вы можете это отредактировать зайдя в файл настройки проекта 'settings.py':

sudo vim fixmypc_project/fixmypc_project/settings.py

Структура папок для настройки Django и Nginx с settings.py на Ubuntu 20

Нам нужна переменна, которая называется ALLOWED_HOSTS. Например вы можете добавить следующие значения в эту переменную:

  • ['*'] - django будет работать с любого адреса. Удобно, когда ваш сервер на DHCP и не придется менять настройки каждый раз при изменении адреса. Эти настройки нельзя применять, если ваш сервер является публичным;
  • ['192.168.3.120'] - запросы будут обрабатываться, если пользователь зашел по этому адресу;
  • ['domain.com'] - запросы будут приниматься, если пользователь зашел по этому доменному имени;
  • ['.domain.com'] - запросы будут приниматься, если пользователь зашел по этому доменному имени или по любому поддомену.

Все эти значения можно сочетать. Обычно настройки имеют доменное имя и ip аддрес. Например:

ALLOWED_HOSTS = ['domain.local', 'www.domain.local', '192.168.3.2']

Так как у меня DHCP и виртуальная машина, я буду применять '*':

Разрешенные подключения ALLOWED_HOSTS для работы Django на Ubuntu 20

На строке 28, со скриншота выше, так же можно увидеть переменную 'DEBUG'. Эта переменная может принимать следующие значения:

  • True - будут выводиться ошибки по котором можно выявить неисправность. Если это публичный сайт (production) - не используется;
  • False - ошибки выводиться не будут.

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

В этом же файле есть переменная DATABASE, в которой прописываются настройки базы. Нам понадобится:

  • Название базы - в моем случае это 'fixmypc_database';
  • Имя пользователя - в моем случае это 'fixmypc_database_user';
  • Пароль пользователя - в моем случае это 'password';
  • Пакет, с помощью которого будет выполняться подключение к базе - в статье мы устанавливали 'psycopg2-binary', а вызывается он как 'postgresql_psycopg2'.

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

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

Настройка базы данных для работы Django и PostgreSQL для работы в ubuntu 20

В работе веб-сайтов есть понятие статических файлов. Это файлы, которые обрабатываются не Django, а Nginx. Например это могут быть файлы: css, jpg, mp4, js и т.д. Для таких файлов создается отдельная директория и она указывается в настройке 'STATIC_ROOT'.

Часто, переменная 'STATIC_ROOT' объявляется вместе с 'BASE_DIR'. Переменная 'BASE_DIR' автоматически создается в начале этого файла и хранит полный путь до проекта.

Можно объявить переменную следующим образом:

STATIC_ROOT = BASE_DIR / 'static'

В таком случае папка, куда будут складываться все статические файлы, будет иметь следующий путь:

Создание статических файлов и папки static в Django на Ubuntu 20

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

sudo python3 fixmypc_project/manage.py collectstatic

Сбор статических файлов в Django на Ubuntu 20

Настройка выше сработает для Django установленной по умолчанию (старше чем версия 3.0). Если бы вы, при установке через pip, указывали другие версии, младше чем 3.0, пришлось бы указать путь следующим образом:

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

Настройка STATIC_ROOT для работы с Django и Nginx

Если множество дополнительных настроек, например MEDIA_ROOT (директория куда будут загружаться меди файлы) или STATICFILES_DIRS (дополнительные места сбора статических файлов), но они не будут рассматриваться в рамках этой статьи. Настройки файла settings.py закончены и его можно сохранить.

Теперь вы можете протестировать запуск Django. Это можно сделать двумя способами. Следующая команда запускает Django по умолчанию, слушая подключения только локально и по порту 8000:

sudo python3 fixmypc_project/manage.py runserver

Запуск сервера Django в тестовом режиме на Ubuntu 20

Работу Django можно проверить следующей командой:

curl localhost:8000

Проверка работы Django через curl в ubuntu 20

В случае выше вы сможете проверить работу Django только локально (на том компьютере где он установлен). Если вы указали в переменной 'ALLOWED_HOSTS' IP адрес, который принадлежит вашему Ubuntu, или знак '*', то вы сможете выполнить следующую команду и посмотреть на работу Django с другого компьютера:

sudo python3 fixmypc_project/manage.py runserver 0.0.0.0:8000

Запуск сервера Django методом bind на Ubuntu 20

Проверка работы Django на Ubuntu 20

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

sudo ufw allow 8000

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

 

Дополнительные настройки Django

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

sudo python3 fixmypc_project/manage.py makemigrations
sudo python3 fixmypc_project/manage.py migrate

Выполнение миграций Django и проверка соединения с базой на Ubuntu 20

Успешно примененные миграции говорят о нормально работе Django с postgresql.

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

sudo python3 fixmypc_project/manage.py createsuperuser

Создание администратора Django на Ubuntu 20

На этом этапе мы так же можем проверить работу команды gunicorn с Django выполнив следующее. Для его запуска понадобится файл wsgi.py, созданный Django автоматически. Сам файл находится по следующему пути:

Подключение файла wsgi.py в Django

Обратите внимание, что в команде ниже 'fixmypc_project.wsgi' - это путь, состоящий из папки и файла (без расширения), разделенных точкой:

gunicorn --bind 0.0.0.0:8000 fixmypc_project.wsgi

Проверка работы gunicorn и Django на Ubuntu 20

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

deactivate

Выход из виртуального окружения Python

 

Создание сокета и настройка WSGI Gunicorn

Gunicorn - это WSGI сервер, который поможет Nginx общаться с Django. Для его работы можно использовать отдельный файл, но более надежным способом является создание файла сокета и сервиса. Файл сокета используется для обмена информацией между процессом Nginx,Django и Gunicorn. Когда к сокету будет выполняться подключение он автоматически запустит сервис Gunicorn.

Создадим и откроем файл по следующему пути:

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

В этот файл нужно поместить следующую информацию:

[Unit]
Description=Gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Теперь создадим сервис по следующему пути:

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

В этот файл мы должны поместить следующую информацию (они будут одинаковые у всех в рамках этой статьи):

  • Unit - директива, которая описывает сервис и говорит, что он может быть запущен только после загрузки "сети" (network target) и если gunicorn.socket работает;
  • Install - создаст файл в директории 'ls /etc/systemd/system/multi-user.target.wants/' для запуска сервиса.

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

  • User и Group определяют от чьего имени будет запускаться сервис;
  • WorkingDirectory - директория отсносительно которой будут запускаться часть файлов в ExecStart;
  • ExecStart - процесс, который нужно запустить в качестве сервиса. Скорее всего он у вас так же будет по следующему пути '/usr/local/bin/gunicorn', но вы можете это перепроверить командой 'which gunicorn'.

Параметры '/usr/local/bin/gunicorn' говорят о следующем:

  • access-logfile - со значением '-' говорит, что ошибки будут писаться в stdout;
  • workers - количество возможных процессов, для обработки запросов. Рассчитывается из количества 2-4 умноженное на количество ядер;
  • bind - связанный с сервисом сокет (будет таким же у всех);
  • fixmypc_project.wsgi:application - путь, относительно 'WorkingDirectory', где расположен файл wsgi.py. В качестве разделителя '.'. Application - это название переменной в этом файле.

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

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

[Service]
User=alex
Group=alex
WorkingDirectory=/fixmypc_folder/fixmypc_project
ExecStart=/usr/local/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          fixmypc_project.wsgi:application

[Install]
WantedBy=multi-user.target

Запустим сокет:

sudo systemctl enable --now gunicorn.socket
systemctl status gunicorn.socket

У нас не должно появляться каких либо ошибок.

Включение и проверка работы сокета gunicorn на Ubuntu 20

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

systemctl status gunicorn.service

Включение и проверка работы сервиса gunicorn на Ubuntu 20

Сервис будет активирован автоматически при первом запросе. Этот запрос мы можем послать через сокет используя curl:

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

Успешное выполнение команды покажет следующий вывод:

Выполнение запроса к сокету gunicorn через curl на Ubuntu 20

 

Проверка работы gunicorn

Gunicorn является ключевым сервисом и его проблемы с ним тяжело диагностировать. Для проверки его состояния вы можете выполнить следующую команду:

systemctl status gunicorn.socket

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

Просмотр статуса gunicorn на Ubuntu 20

У вас так же должен существовать файл в директории run:

file /run/gunicorn.sock

Проверка существования файла Gunicorn на ubuntu 20

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

sudo journalctl -u gunicorn.socket

Так же, если вы видите ошибки, стоит перепроверить файлы socket и service созданные выше.

 

Настройка Nginx для работы с Gunicorn

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

vim /etc/nginx/sites-available/fixmypc_site

В этом файле мы должны будем указать несколько параметров. Первое - на каком порту будет работать сайт и его DNS имя. Порт, который используется по умолчанию протоколом HTTP - 80.

DNS имя вы должны знать сами. Вы можете его купить у регистратора доменов, зарегистрировать в локальном DNS сервере либо прописать его в файле hosts. Ниже пример для домена fixmypc.ru:

server {
   listen 80;
   server_name fixmyc.ru www.fixmypc.ru;
}

Далее нам нужно указать путь до статических файлов (переменная STATIC_ROOT в settings.py), где будут лежать наши файлы: css,js,jpg и т.д. Эта директория будет обрабатываться напрямую Nginx'ом. Если вы шли точно по инструкциям выше, то этот путь будет следующим '/fixmypc_folder/fixmypc_project/static'. В других случаях используйте названия тех директорий, которые создавали вы.

server {
   listen 80;
   server_name fixmyc.ru www.fixmypc.ru;

   location /static/ {
      root /fixmypc_folder/fixmypc_project/static;
   }
}

Нам нужно добавить последнюю директиву, которая будет говорить что при открытии корня сайта '/' нам нужно будет обращаться к Gunicorn сокету и получать информацию от него. Скорее всего она будет одинаковой во всех случаях (если вы не меняли названий сокетов и сервисов):

server {
   listen 80;
   server_name fixmyc.ru www.fixmypc.ru;

   location /static/ {
      root /fixmypc_folder/fixmypc_project/static;
   }

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

Далее мы можем сохранить файл и установить символическую ссылку в каталоге, который читает nginx. Заменить название "fixmypc_site" на то, которое используете вы:

sudo ln -s /etc/nginx/sites-available/fixmypc_site /etc/nginx/sites-enabled/

В каталоге sites-enabled так же расположен сайт, который открывает по умолчанию на 80 порту. Вы можете убрать у него директиву "default_server" и поставить ее в свой файл либо просто удалить этот файл:

sudo rm /etc/nginx/sites-enabled/default

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

sudo nginx -t

Создание конфигурации Nginx для работы с Django и Gunicorn

Перезапустим сервис Nginx что бы наши настройки применились и проверим его статус:

sudo systemctl reload nginx.service
systemctl status nginx.service

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

Проверка работы сервиса Nginx на Ubuntu

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

curl localhost

Проверка работы Django с Gunicorn и Nginx

Настройка закончена.

...

Теги: #python #django #ubuntu


Популярные тэги
О блоге
Этот блог представляет собой конспекты выученного материала, преобретенного опыта и лучшие практики в системном администрировании и программировании.