Установка виртуального окружения, Gunicorn и списка зависимостей
Подготовка проекта
Перед выкладкой убедитесь, что:
- проект лежит в git-репозитории (GitHub, GitLab) и в нём нет секретов;
requirements.txtактуален:pip freeze > requirements.txt;.gitignoreисключаетvenv/,db.sqlite3,.env,media/,staticfiles/.
Настройки для продакшена
Секреты и параметры окружения — из переменных окружения:
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
DEBUG = os.environ.get("DJANGO_DEBUG", "0") == "1"
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")
CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in ALLOWED_HOSTS if h]
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_ROOT = BASE_DIR / "media"
DEBUG = False
С DEBUG = True любой посетитель при ошибке увидит код, настройки и пути вашего проекта. В продакшене — только False.
Новый секретный ключ:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
Django может сам проверить настройки безопасности:
python manage.py check --deploy
Установка на сервере
sudo apt install python3 python3-venv python3-dev git build-essential -y
cd ~
git clone https://github.com/you/blog.git
cd blog
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install gunicorn
Файл окружения /home/deploy/blog/.env:
DJANGO_SECRET_KEY=сгенерированный-ключ
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=myblog.ru,www.myblog.ru
DB_NAME=blog
DB_USER=blog
DB_PASSWORD=надёжный-пароль
DB_HOST=localhost
chmod 600 .env
Для ручных команд загрузите переменные в текущую сессию:
set -a; source .env; set +a
python manage.py migrate
python manage.py collectstatic --noinput
python manage.py createsuperuser
collectstatic собирает статику всех приложений (включая админку) в STATIC_ROOT — её будет раздавать NGINX.
Gunicorn
Gunicorn — WSGI-сервер для продакшена: запускает несколько процессов-воркеров с вашим Django-приложением.
Проверка:
gunicorn --bind 0.0.0.0:8000 mysite.wsgi:application
Временно откройте порт (sudo ufw allow 8000) и зайдите на http://IP:8000 — сайт откроется без стилей (статику раздаст NGINX). Затем остановите (Ctrl+C) и закройте порт (sudo ufw delete allow 8000).
Число воркеров — по формуле 2 × ядра + 1 (для 1 ядра — 3).
Служба systemd
Чтобы Gunicorn работал постоянно, перезапускался при сбое и стартовал вместе с сервером, оформим его службой.
Сокет /etc/systemd/system/gunicorn.socket:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Служба /etc/systemd/system/gunicorn.service:
[Unit]
Description=gunicorn daemon for blog
Requires=gunicorn.socket
After=network.target
[Service]
User=deploy
Group=www-data
WorkingDirectory=/home/deploy/blog
EnvironmentFile=/home/deploy/blog/.env
ExecStart=/home/deploy/blog/venv/bin/gunicorn \
--workers 3 \
--bind unix:/run/gunicorn.sock \
mysite.wsgi:application
[Install]
WantedBy=multi-user.target
Gunicorn слушает unix-сокет — файл, через который с ним будет общаться NGINX. Это быстрее и безопаснее открытого порта.
sudo systemctl daemon-reload
sudo systemctl enable --now gunicorn.socket
sudo systemctl status gunicorn.socket
curl --unix-socket /run/gunicorn.sock localhost # первый запрос запустит службу
sudo systemctl status gunicorn
Полезные команды:
| Команда | Что делает |
|---|---|
sudo systemctl restart gunicorn |
Перезапуск (после обновления кода) |
sudo systemctl status gunicorn |
Состояние |
sudo journalctl -u gunicorn -f |
Логи в реальном времени |
Итог
- Секреты — в
.envна сервере (права 600), в коде —os.environ. DEBUG = False, правильныеALLOWED_HOSTS,check --deploy.- Проект:
git clone→venv→pip install -r requirements.txt→migrate→collectstatic. - Gunicorn запускается как служба systemd и слушает unix-сокет.
Практика решено 0 из 6
Почему нельзя использовать python manage.py runserver в продакшене?
Сделайте настройки безопасными для продакшена: DEBUG берётся из переменной окружения DJANGO_DEBUG
(истина только при значении "1"), SECRET_KEY — из DJANGO_SECRET_KEY (через os.environ[...]),
ALLOWED_HOSTS — из DJANGO_ALLOWED_HOSTS, разделённых запятыми.
import os
DEBUG = os.environ.get("DJANGO_DEBUG", "0") == "1"
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "").split(",")
Какой командой запустить Gunicorn для проекта mysite на порту 8000 со всеми интерфейсами (для проверки)?
gunicorn --bind 0.0.0.0:8000 mysite.wsgi:applicationДопишите секцию [Service] юнита systemd для Gunicorn: пользователь deploy, группа www-data,
рабочая папка /home/deploy/blog, команда запуска — /home/deploy/blog/venv/bin/gunicorn
с 3 воркерами, привязкой к сокету unix:/run/gunicorn.sock и приложением mysite.wsgi:application.
[Unit]
Description=gunicorn daemon for blog
Requires=gunicorn.socket
After=network.target
[Service]
User=deploy
Group=www-data
WorkingDirectory=/home/deploy/blog
EnvironmentFile=/home/deploy/blog/.env
ExecStart=/home/deploy/blog/venv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.sock mysite.wsgi:application
[Install]
WantedBy=multi-user.target
Сколько воркеров Gunicorn рекомендует документация как отправную точку?
Разверните проект на сервере, запустите Gunicorn как службу systemd и выполните sudo systemctl is-active gunicorn. Вставьте вывод.
Войдите, чтобы отмечать пройденные уроки.