В этой статье будет рассмотрена установка и настройка фреймворка 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 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 сами:
sudo systemctl enable --now nginx
systemctl status nginx
Вы так же сможете посмотреть на работу nginx с другого компьютера указав IP адрес. IP адрес можно узнать с помощью следующей команды:
ip a
Если вы не можете открыть сайт используя свой ip адрес, то можно попробовать открыть порты в фаерволле:
sudo ufw allow http
sudo ufw allow https
Создание пользователей и базы данных PosgreSQL
С базой данных будет работать Django. Что бы это было возможно мы должны создать базу данных и ее пользователя.
При установке PostgreSQL автоматически создается пользователь postgres имеющий все права для управления сервером баз данных. С помощью его мы создадим пользователя и дадим права на базу. psql - это команда, которая позволяет подключаться к серверу базы данных локально:
sudo -u postgres psql
С помощью следующей команды мы создадим базу данных. Вы можете выбрать любое имя. Важно запомнить название базы, так как без него вы не сможете выполнить дальнейшие настройки. В моем случае база будет называться 'fixmypc_database':
CREATE DATABASE fixmypc_database;
Создадим пользователя базы данных и дадим ему пароль. В моем случае пользователь 'fixmypc_database_user', а пароль 'password':
CREATE USER fixmypc_database_user WITH PASSWORD 'password';
Следующие настройки не обязательны, но они являются рекомендованными и описаны в документации 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';
Что бы пользователь мог подключаться к базе мы должны дать соответствующие права. Это можно сделать с помощью следующей команды (название так же замените, если вам понадобится):
GRANT ALL PRIVILEGES ON DATABASE fixmypc_database TO fixmypc_database_user;
Настройки базы завершены. Выйдем из консоли:
\q
Создание виртуального окружения и работа с pip
Виртуальное окружение позволяет корректно хранить и управлять версиями пакетов, которые мы будем устанавливать с помощью pip (python3-pip). Этот пакет устанавливается отдельно. Что бы создать виртуальное окружение вы должны определиться с местом где будет храниться основная часть вашего Django сайта. В моем случае это будет корень Ubuntu '/', а папка будет называться fixmypc_folder. Я рекомендую запомнить название и путь, так как в дальнейшем все эти настройки еще понадобятся.
Создадим папку:
sudo mkdir /fixmypc_folder
Перейдем в папку:
cd /fixmypc_folder
Мое окружение будет называться 'env' и это имя тоже понадобится для дальнейших настроек:
sudo python3 -m venv env
ls
Далее мы можем активировать виртуальное окружение:
source env/bin/activate
Как вы видите по скриншоту выше переход в виртуальное окружение всегда обозначается его названием в начале командной строки. Так как мое виртуальное окружение называется env, у меня стало отображаться (env).
Далее мы установим пакеты, которые понадобятся для работы Django:
- django - фреймворк, который мы используем;
- gunicorn - WSGI сервер;
- psycopg2-binary - библиотека для подключения к PostgreSQL.
sudo pip3 install django gunicorn psycopg2-binary
Создание проекта Django и его настройка c settings.py
После того как вы установили нужные пакеты через pip нужно создать проект. В случае Django, создание проекта, это просто копирование шаблонных файлов объединенное в одну команду.
Проекту тоже нужно дать имя. В моем случае это будет 'fixmypc_project':
sudo django-admin startproject fixmypc_project
Теперь я имею следующую структуру папок, где проект и виртуальное окружение находятся на одном уровне:
По умолчанию в Django установлены настройки, которые разрешают просмотр веб-сайта только локально (localhost/127.0.0.1). Вы можете это отредактировать зайдя в файл настройки проекта 'settings.py':
sudo vim fixmypc_project/fixmypc_project/settings.py
Нам нужна переменна, которая называется 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 и виртуальная машина, я буду применять '*':
На строке 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, а Nginx. Например это могут быть файлы: css, jpg, mp4, js и т.д. Для таких файлов создается отдельная директория и она указывается в настройке 'STATIC_ROOT'.
Часто, переменная 'STATIC_ROOT' объявляется вместе с 'BASE_DIR'. Переменная 'BASE_DIR' автоматически создается в начале этого файла и хранит полный путь до проекта.
Можно объявить переменную следующим образом:
STATIC_ROOT = BASE_DIR / 'static'
В таком случае папка, куда будут складываться все статические файлы, будет иметь следующий путь:
С помощью следующей команды мы соберем все статические файлы, и перенесем их в эту папку (она создастся автоматически):
sudo python3 fixmypc_project/manage.py collectstatic
Настройка выше сработает для Django установленной по умолчанию (старше чем версия 3.0). Если бы вы, при установке через pip, указывали другие версии, младше чем 3.0, пришлось бы указать путь следующим образом:
STATIC_ROOT = os.path.joing(BASE_DIR, 'static/')
Если множество дополнительных настроек, например MEDIA_ROOT (директория куда будут загружаться меди файлы) или STATICFILES_DIRS (дополнительные места сбора статических файлов), но они не будут рассматриваться в рамках этой статьи. Настройки файла settings.py закончены и его можно сохранить.
Теперь вы можете протестировать запуск Django. Это можно сделать двумя способами. Следующая команда запускает Django по умолчанию, слушая подключения только локально и по порту 8000:
sudo python3 fixmypc_project/manage.py runserver
Работу Django можно проверить следующей командой:
curl localhost:8000
В случае выше вы сможете проверить работу Django только локально (на том компьютере где он установлен). Если вы указали в переменной 'ALLOWED_HOSTS' IP адрес, который принадлежит вашему Ubuntu, или знак '*', то вы сможете выполнить следующую команду и посмотреть на работу Django с другого компьютера:
sudo python3 fixmypc_project/manage.py runserver 0.0.0.0:8000
Если вы не можете открыть Django с другого компьютера и в консоли Ubuntu у вас не появляются ошибки, то возможно проблема в фаерволле. Вы можете открыть порт 8000 (или другой, который указали) что бы протестировать его работу следующей командой:
sudo ufw allow 8000
Это не обязательно т.к. сетевое подключение, в дальнейшем, будет принимать nginx, а не Django.
Создание первого приложения во фреймворке Python Django 3
Дополнительные настройки Django
Для того, что бы проверить работу базы данных и что бы Django создал нужные для него таблицы в базе данных нам нужно выполнить миграции. Миграции Django автоматически выполняются в 2 этапа: создание кода и его применение к базе:
sudo python3 fixmypc_project/manage.py makemigrations
sudo python3 fixmypc_project/manage.py migrate
Успешно примененные миграции говорят о нормально работе Django с postgresql.
Мы можем создать пользователя, который в дальнейшем будет администратором Django, с помощью следующей команды:
sudo python3 fixmypc_project/manage.py createsuperuser
На этом этапе мы так же можем проверить работу команды gunicorn с Django выполнив следующее. Для его запуска понадобится файл wsgi.py, созданный Django автоматически. Сам файл находится по следующему пути:
Обратите внимание, что в команде ниже 'fixmypc_project.wsgi' - это путь, состоящий из папки и файла (без расширения), разделенных точкой:
gunicorn --bind 0.0.0.0:8000 fixmypc_project.wsgi
Работа в виртуальном окружении закончена. Вы можете выйти из него выполнив следующую команду:
deactivate
Создание сокета и настройка 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 следующей командой, он будет не активен:
systemctl status gunicorn.service
Сервис будет активирован автоматически при первом запросе. Этот запрос мы можем послать через сокет используя curl:
sudo curl --unix-socket /run/gunicorn.sock localhost
Успешное выполнение команды покажет следующий вывод:
Проверка работы gunicorn
Gunicorn является ключевым сервисом и его проблемы с ним тяжело диагностировать. Для проверки его состояния вы можете выполнить следующую команду:
systemctl status gunicorn.socket
Вывод команды должен быть следующим:
У вас так же должен существовать файл в директории run:
file /run/gunicorn.sock
Для диагностики ошибок вы можете посмотреть журнал логов:
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 что бы наши настройки применились и проверим его статус:
sudo systemctl reload nginx.service
systemctl status nginx.service
Стрелки ниже указывают, что сервис работает в данный момент и он включится сам после перезагрузки компьютера:
После этого вы сможете открыть сайт в браузере или выполнить следующую команду:
curl localhost
Настройка закончена.
...