Автор: dcontm 25 февраля 2020
Разворачиваем Django проект с Postgres, Nginx и Gunicorn на Ubuntu 18.04
Предисловие
В сегодняшнем руководстве мы рассмотрим, как развернуть ваш проект в production. Эта статья является вольным пересказом великолепного руководства на DigitalOcean. Предполагается, что у вас есть сервер Ubuntu 18.04, предварительно настроенный. Как настроить сервер, вы можете посмотреть здесь. Иcпользуемая версия Python - 3.6.9. В качестве базы данных будем использовать PostgreSQL, настроим Gunicorn для общения с нашим Django приложением, также будем использовать сервер Nginx. Nginx будет будет обслуживать все входящие запросы к нашему приложению, передавая их Gunicorn.
- Установка необходимых пакетов.
- Создание и настройка базы данных.
- Настройка виртуальной среды.
- Создание и настройка нового проекта Django.
- Настройка и демонизация сервера Gunicorn.
- Настройка Nginx.
- Устранение неисправностей.
Установка необходимых пакетов
Для начала обновим локальный индекс пакетов apt, воспользовавшись следующей командой:
Далее установим все необходимые нам пакеты:
После выполнения команды на ваш удаленный компьютер будут установлены библиотеки разработки Python3, система базы данных PostgreSQL, библиотека взаимодействия с ней, а также веб-сервер Nginx.
Создание и настройка базы данных
Следующим шагом будет создание базы данных для нашего проекта и нового пользователя, которому будут принадлежать база данных. По умолчанию при установке PostgreSQL автоматически был создан пользователь с именем postgres. Сейчас мы сможем использовать его для выполнения некоторых административных задач. Для этого войдем в интерактивную сессию Postgres:
В открывшемся интерактивном меню мы сможем установить некоторые необходимые нам настройки, обратите внимание, что каждая строка должна заканчиваться точкой с запятой. Для начала создадим базу данных для нашего проекта:
Далее создаем базу данных пользователя для нашего проекта. Убедитесь, что вы выбрали надежный пароль (пароль в одинарных кавычках):
После этого мы изменим некоторые параметры подключения для пользователя, которого мы только что создали. Мы установим кодировку по умолчанию UTF-8, которую ожидает Django. Мы также установим схему изоляции транзакции по умолчанию «read commit», которая блокирует чтение из незафиксированных транзакций. Наконец, мы устанавливаем часовой пояс. По умолчанию наши проекты Django будут настроены на использование UTC. Это все рекомендации самого проекта Django:
postgres=# ALTER ROLE my_user SET default_transaction_isolation TO 'read committed';
postgres=# ALTER ROLE my_user SET timezone TO 'UTC';
Последним шагом будет наделение нашего пользователя возможностью управлять созданной базой данных:
Теперь можно выйти из интерактивного режима:
Postgres настроен так, что Django может подключаться и управлять информацией своей базы данных.
Настройка виртуальной среды
Виртуальную среду создадим с помощью команды virtualenv, которую установим при помощи pip. Предварительно обновим pip:
$ sudo -H pip3 install virtualenv
После установки virtualenv мы можем приступить к созданию каталогов для нашего проекта:
$ cd ~/my_project
Теперь после того как мы перешли в созданный нами каталог, создадим нашу виртуальную среду:
Внутри будет установлена локальная версия Python и pip, это защитит нас от конфликтов версий различных пакетов. Осталось активировать нашу виртуальную среду:
После активации виртуальной среды мы можем установить Django, Gunicorn и psycopg2 (драйвер для работы с PostgreSQL):
Выполнив все перечисленные действия, мы имеем все необходимое для запуска нашего Django проекта.
Создание и настройка нового проекта Django
Давайте приступим к созданию нового проекта Django. Для этого, находясь в каталоге проекта с активированным виртуальным окружением, создадим новый проект:
После выполнения этой команды вы получите следующую иерархию каталогов и файлов:
Следующим шагом будет изменение настроек проекта. Для этого откроем файл конфигурации, выполнив команду:
Найдите и измените следующие переменные:
~/my_project/django_project/django_project/settings.py
#Укажите ваш домен и хост, не хабудьте включить в список localhost
ALLOWED_HOSTS = ['ваш домен или IP', 'localhost']
..........................................................................................
# Измените настройки используемой базы данных
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'my_database',
'USER': 'my_user',
'PASSWORD': 'my_password',
'HOST': 'localhost',
'PORT': '',
}
}
..........................................................................................
# Укажите местоподлжение ваших статических файлов
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
После внесения всех изменений сохраните и закройте файл. Вы можете получить больше информации по настройкам Django в открытой среде тут.
Нам осталось выполнить несколько заключительных настроек перехода к следующему этапу. Создадим и добавим исходные схемы базы данных Django в нашу базу PostgreSQL:
(venv) $ django_project/manage.py migrate
Cоздадим суперпользователя с правами администратора:
Укажите все данные, запрашиваемые командой, используйте надежный пароль, все это пригодится для входа в панель администратора.
Теперь нам нужно собрать все статические файлы в одном месте, которые мы указали в настройках проекта:
Для того, чтобы проверить работоспособность нашего Django приложения, запустим его. Если вы выполнили настройку операционной системы в соответствии с предыдущей статьей, у вас должен быть настроен брандмауер UFW, отбрасывающий все подлючения, кроме как OpenSSH (порт), поэтому первым действием будет открытие дополнительного порта:
Наконец мы можем запустить сервер разработки:
Откройте браузер и перейдите по адресу http//:<ваш домен или IP>:8000, вы должны увидеть экран приветсвия Django.
Чтобы остановить сервер разработки, находясь в консоле, нажмите CTRL+C. После успешного завершения предыдущих шагов вы можете выйти из виртуального окружения.
Настройка и демонизация сервера Gunicorn
Прежде чем заняться демонизацией Gunicorn, давайте убедимся в его работоспособности на переднем плане:
Здесь мы запустили Gunicorn, указав относительный путь точки входа в наше приложение. Теперь, если сервер успешно запустился, вы можете перейти в браузер и протестировать ваше приложение по адресу http//:<ваш домен или IP>:8000. Обратите внимание, что оформление вашего приложения будет без css стилей, так как мы не указали Gunicorn, где найти статику. Позднее работу со статическими данными возьмет на себя Nginx.
Самое время заняться автоматизацией запуска, перезапуска и остановки сервера Gunicorn. Для этого мы создадим файл службы systemd и сокет. Gunicorn сокет будет создан при загрузке и будет прослушивать входящие соединения.
Для начала создадим для Gunicorn сокет службы systemd:
Добавим и сохраним в открывшемся файле следующее:
/etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Затем создайте и служебный файл systemd для Gunicorn. Имя файла должно соответствовать имени сокета, за исключением его разрешения.
Поместите в него следующее содержимое:
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=my_user
Group=www-data
WorkingDirectory=/home/my_user/my_project/django_project
ExecStart=/home/my_user/my_project/venv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.wsgi:application
[Install]
WantedBy=multi-user.target
На этом наш сервисный файл systemd завершен - можете закрыть и сохранить его. Теперь нам нужно запустить и включить сокет Gunicorn. Это создаст файл сокета /run/gunicorn.sock сейчас и при загрузке. Когда будет установлено соединение с этим сокетом, gunicorn.service будет обрабатывать его:
$ sudo systemctl enable gunicorn.socket
Чтобы проверить, что все запустилось и работает успешно, выполним проверку работы процесса:
Проверим наличие файла сокета:
В случае если при запуске возникают какие-то ошибки, вы можете посмотреть журнал логирования с помощью утилиты journalctl:
В большинстве случаев неполадки возникают в следствии неправильно указанных путей до исполняемых файлов.
В настоящее время, хоть мы и успешно запустили сокет, gunicorn.service ещё не активен, поскольку он не получал никаких подключений. Мы можем убедиться в этом:
Вывод будет следующим:
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Чтобы проверить механизм активации сокета, мы можем отправить соединение через сокет curl, набрав:
Вы должны увидеть вывод HTML кода вашего приложения. Чтобы убедиться, что Gunicorn работает, введите:
В выводе вы должны увидеть, что Gunicorn активен:
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
Active: active (running) since Sat 2020-02-08 23:47:53 UTC; 6s ago
Main PID: 27851 (gunicorn)
Tasks: 4 (limit: 1124)
CGroup: /system.slice/gunicorn.service
├─27851 /home/my_user/my_project/venv/bin/python3 /home/dcontm/tiny/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock django_project.wsgi:application
├─27854 /home/my_user/my_project/venv/bin/python3 /home/dcontm/tiny/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock django_project.wsgi:application
├─27855 /home/my_user/my_project/venv/bin/python3 /home/dcontm/tiny/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock django_project.wsgi:application
└─27858 /home/my_user/my_project/venv/bin/python3 /home/dcontm/tiny/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock django_project.wsgi:application
Если выходные данные curl или systemctl status указывают на то, что возникла проблема, проверьте журналы для получения дополнительной информации:
Обратите внимание, если вы внесете изменения в /etc/systemd/system/gunicorn.service файл, перезагрузите демон, чтобы перезапустить процесс Gunicorn в новой конфигурации, набрав:
$ sudo systemctl restart gunicorn
Убедитесь, что все работает, прежде чем продолжить.
Настройка Nginx
После того как вы убедились, что все работает, пришло время сконфигурировать Nginx на передачу всех запросов Gunicorn серверу. Для этого создадим файл конфигурации нашего проекта:
В отрывшемся файле сохраните следующие настройки:
/etc/nginx/sites-available/myproject
server {
listen 80;
server_name домен и/или IPсервера;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/my_user/my_project/django_project;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
В настройках мы указали, что Nginx должен прослушивать 80 порт и отвечать на доменное имя и/или IP нашего сервера. Также мы указали расположение наших статических файлов и favicon изображения (при этом игнорируем все ошибки, связанные с ним). В последнем блоке мы настроили прокси, теперь все запросы Nginx передает нашему Gunicorn сокету. После того как вы закончили, сохраните и закройте файл. Теперь мы можем применить наш файл конфигурации, связав его с sites-enabled каталогом. Для этого создадим символьную ссылку:
Проверьте ваш файл конфигурации на синтаксические ошибки:
Если все хорошо, перезапустите Nginx:
Наконец нам нужно настроить наш брандмауэр. Для этого удалим из разрешенных порт 8000, который мы использовали для тестирования, и откроем для трафика 80 порт:
$ sudo ufw allow 'Nginx Full'
Теперь вы можете открыть браузер и просмотреть ваше приложение, использовав для этого доменное имя или IP-адрес.
Устранение неисправностей
При различных возникающих ошибках вы можете почерпнуть информацию из различных журналов логирования:
- Проверьте журналы процесса 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
Не забывайте после изменения конфигурации перезагружать демон службы или сервера:
$ sudo systemctl restart nginx
$ sudo systemctl restart gunicorn.socket gunicorn.service
$ sudo systemctl daemon-reload
Резюме
В этом руководстве мы установили Django в виртуальной среде, настроили сервер Gunicorn для взаимодействия с Django. После этого мы настроили Nginx в качестве обратного прокси-сервера. Статья получилась довольно объемной, тем не менее вся изложенная информация является необходимой и достаточной для развертывания вашего Django приложения в production.