VPS для Django на production: gunicorn детально
Production-деплой Django — это gunicorn как WSGI-сервер, nginx впереди и правильно собранная статика. Пройдём весь путь по шагам: venv, gunicorn под systemd через сокет, nginx, collectstatic и TLS.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Схема production-деплоя
Встроенный сервер runserver не предназначен для боевой эксплуатации. На production Django запускают через WSGI-сервер — чаще всего gunicorn, который держит пул воркеров и обрабатывает параллельные запросы.
Перед gunicorn ставят nginx: он терминирует TLS, отдаёт статику и медиа, а динамику проксирует в gunicorn через unix-сокет. Такая связка стабильна и хорошо держит нагрузку.
- gunicorn — WSGI-сервер, воркеры под запросы.
- nginx — TLS, статика, reverse proxy.
- collectstatic — сбор статики в одну папку для nginx.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для DjangoПодготовка окружения
Ставим Python, создаём виртуальное окружение и заводим зависимости. Отдельный пользователь повышает безопасность.
sudo apt update
sudo apt install -y python3 python3-venv python3-pip nginx git
sudo mkdir -p /opt/djangoapp && cd /opt/djangoapp
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt gunicorn
Настройки Django для прода
В settings.py переключаем режим: выключаем DEBUG, задаём ALLOWED_HOSTS и путь для собранной статики. Секретный ключ берём из окружения.
DEBUG = False
ALLOWED_HOSTS = ['example.com', 'www.example.com']
STATIC_ROOT = '/opt/djangoapp/staticfiles'
STATIC_URL = '/static/'
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
Собираем статику и применяем миграции:
python manage.py collectstatic --noinput
python manage.py migrate
Для базы данных на production почти всегда берут PostgreSQL. Параметры подключения выносите в переменные окружения, а не хардкодьте в settings.py — так один и тот же код работает и локально, и на сервере.
sudo apt install -y postgresql libpq-dev
sudo -u postgres createdb djangoapp
pip install psycopg2-binary
gunicorn под systemd через сокет
Надёжнее всего запускать gunicorn на unix-сокете и управлять им через systemd. Число воркеров обычно берут как 2 × ядра + 1.
[Unit]
Description=gunicorn for Django
After=network.target
[Service]
User=appuser
WorkingDirectory=/opt/djangoapp
ExecStart=/opt/djangoapp/venv/bin/gunicorn \
--workers 3 \
--bind unix:/opt/djangoapp/gunicorn.sock \
myproject.wsgi:application
Restart=always
Environment=DJANGO_SECRET_KEY=changeme
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now gunicorn
sudo systemctl status gunicorn
journalctl -u gunicorn -f
Для плавных деплоев без сброса всех соединений gunicorn поддерживает graceful reload по сигналу HUP: мастер поднимает новых воркеров и мягко гасит старых. Это удобно связать с командой перезапуска после выкатки кода.
sudo systemctl reload gunicorn
nginx: статика и проксирование
nginx сам отдаёт файлы из STATIC_ROOT, а динамику передаёт в сокет gunicorn. Это разгружает Python и ускоряет отдачу ассетов.
server {
listen 80;
server_name example.com;
location /static/ {
alias /opt/djangoapp/staticfiles/;
}
location / {
proxy_pass http://unix:/opt/djangoapp/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
sudo nginx -t && sudo systemctl reload nginx
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
Ресурсы, железо и частые ошибки
Django-проекты часто упираются в БД и CPU при обработке шаблонов и запросов. AMD EPYC + NVMe у MAATRIX дают быстрый диск для PostgreSQL и отзывчивый рантайм, тарифы от $8/мес и ежедневные бэкапы удобны для боевого сайта. Локации UK/США/РФ и оплата из России (карта РФ, СБП, крипта, MAAT) закрывают вопрос зарубежного сервера.
- DEBUG=True на проде — утечка стектрейсов и настроек, серьёзная дыра.
- Забыли collectstatic — стили и админка без оформления.
- Пустой ALLOWED_HOSTS — Django отвечает ошибкой Bad Request (400).
- Права на сокет — nginx (www-data) должен иметь доступ к gunicorn.sock.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS для DjangoОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
gunicorn или uwsgi?
Оба зрелые WSGI-серверы. gunicorn проще в настройке и документации, поэтому его чаще выбирают для Django. uwsgi гибче, но сложнее.
Сколько воркеров gunicorn нужно?
Стартовая формула — 2 × число ядер + 1. Подбирайте под реальную нагрузку и объём RAM, следя за потреблением памяти на воркер.
Как обслуживать медиа-файлы?
Загружаемые пользователями медиа отдавайте через отдельный location в nginx с alias на MEDIA_ROOT, не через Django.