Перейти к содержанию

Django deployment

Предполагается, что на сервере установлена Ubuntu.

Подготовка#

В этом разделе общая последовательность действий для запуска Django приложения на сервере. Многое в нём зависит от конкретного проекта, поэтому команды и их последовательность может быть совсем другой. Главное, что в результате папка с приложением должна оказаться на сервере, а также должно быть создано виртуальное окружение Python (не обязательно через venv) со всеми зависимостями проекта.

Установка Python#

# Для начала обновим установленные пакеты
sudo apt update
sudo apt upgrade

# Не забудьте указать нужную версию python
sudo apt install python3.10 python3.10-venv -y

Python может сходу не установиться и из-за следующей ошибки.

E: Unable to locate package python3.10
E: Couldn't find any package by glob 'python3.10'
E: Unable to locate package python3.10-venv
E: Couldn't find any package by glob 'python3.10-venv'

Нужно просто добавить репозиторий со списками пакетов Python.

sudo add-apt-repository ppa:deadsnakes/ppa   
sudo apt update 
# и снова пробуем установить python

Клонируем проект#

На сервере создаём SSH ключ и копируем его в раздел Deploy keys (в случае GitHub) в настройках репозитория. Если проект публичный, то ключ создавать не обязательно.

ssh-keygen
cat ~/.ssh/id_rsa.pub

А затем клонируем репозиторий.

git clone <repo-url.git>

Если вдруг Git не установлен.

sudo apt install git

Готовим Django к запуску#

Предварительно нужно добавить домен или IP-адрес сервера в ALLOWED_HOSTS в settings.py. Также стоит посмотреть на deployment checklist, который предоставляет документация Django.

Настраиваем виртуальное окружение.

python3.10 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

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

python manage.py makemigrations <app_name>
python manage.py migrate
python manage.py createsuperuser

Gunicorn#

Установка#

# В виртуальном окружении проекта выполнить
pip install gunicorn

# Можно перейти по адресу сервера в браузере на порт 8000 и убедиться,
# что всё работает (ну почти, статики тут не будет)
# Не на всех VDS может быть открыт 8000 порт, в таком случае просто 
# смотрим на отсутствие ошибок
gunicorn --bind 0.0.0.0:8000 django-app-name.wsgi # (1)!
  1. Не забудьте заменить django-app-name.wsgi на реальный путь к wsgi.py файлу проекта.

UNIX-сокет#

Создаём UNIX-сокет в systemd для локального обмена данными между Gunicorn, в котором развёрнут Django, и nginx.

sudo nano /etc/systemd/system/gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

UNIX-сокет можно назвать как угодно

Это особенно полезно, когда на одной машине с помощью Gunicorn нужно развёрнуть сразу несколько приложений. Кстати, имя сокета (gunicorn.sock) не обязательно должно совпадать с названием файла конфигурации сокета для systemd (gunicorn.socket). При этом в командах по типу systemctl status нужно будет использовать имя конфигурационного файла.

Сервис в systemd#

Создаём сервис в systemd, чтобы Gunicorn мог работать как фоновый процесс и запускался вместе с системой.

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

В секции Service нужно указать актуального пользователя и путь до проекта, а также путь до wsgi.py внутри проекта.

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

[Service]
User=user
Group=user
WorkingDirectory=/home/user/project-folder
ExecStart=/home/user/project-folder/venv/bin/gunicorn \
          --access-logfile - \
          --workers 1 \
          --bind unix:/run/gunicorn.sock \
          django-app-name.wsgi:application

[Install]
WantedBy=multi-user.target

Теперь можно запустить сокет и добавить его в автозапуск. systemd автоматически запустит сервис Gunicorn, когда на сокет придёт первый запрос.

# Предварительно перезагружаем systemd
sudo systemctl daemon-reload

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

Nginx#

Установка#

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

sudo apt install nginx

Собираем статику#

Собираем статику (стили, скрипты, картинки) и переносим в /var/www/ - именно этот каталог обычно используется для её хранения. Если поместить статику в другое место, то могут возникнуть проблемы с доступами. nginx просто не сможет работать с нашими файлами, если у него не будет прав на чтение файлов статики и прав на исполнение всех директорий в путях к этим файлам. В конфиге /etc/nginx/nginx.conf можно узнать от имени какого пользователя nginx обрабатывает запросы.

# Команда собирает всю статику Django в папку, которая
# указана в settings.py (см. STATIC_ROOT)
python manage.py collectstatic

# Переносим статику из staticfiles (см. STATIC_ROOT) в /var/www/
# Вместо static может потребоваться указать другую папку (см. STATIC_URL)
sudo mkdir /var/www/django-project
sudo cp -r staticfiles /var/www/django-project/static

Конфиг nginx#

Теперь можно настроить nginx.

# Вместо my-site можно указать название проекта
sudo nano /etc/nginx/sites-available/my-site

Минимальный конфиг.

server {
    listen 80;
    server_name your_domain_or_ip;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /var/www/django-project;
    }

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

Добавляем конфиг в активные конфиги, с которыми сейчас работает nginx.

sudo ln -s /etc/nginx/sites-available/my-site /etc/nginx/sites-enabled

Проверка корректности конфигов.

sudo nginx -t

Если всё в порядке, перезапускаем nginx.

sudo systemctl restart nginx

Если что-то идёт не так...#

Логи NGINX#

# Информация обо всех запросах
sudo tail -f /var/log/nginx/access.log

# Информация обо всех ошибках и предупреждениях
sudo tail -f /var/log/nginx/error.log

# Проверка корректности конфигов
sudo nginx -t

# Очистка логов без необходимости перезапуска NGINX
sudo truncate -s 0 /var/log/nginx/access.log
sudo truncate -s 0 /var/log/nginx/error.log

Логи Gunicorn#

sudo journalctl -u gunicorn.service -f
sudo journalctl -u gunicorn.socket -f

Полезные ссылки#