Представь, что ты создал отличное Django-приложение. Оно работает локально, все тесты проходят. Но как превратить его в работающий веб-сервис, доступный из любой точки мира? Давай разберем процесс развертывания Django от начала до конца — от выбора сервера до базовой конфигурации, которую нужно проверить перед production.
Подготовка к развертыванию Django на сервере
Перед тем как начать развертывание Django на сервере, нужно понять архитектуру production-окружения. Типичная схема включает:
- WSGI-сервер (Gunicorn или uWSGI) — запускает твое Django-приложение
- Веб-сервер (Nginx или Apache) — обрабатывает статические файлы и проксирует запросы
- База данных (PostgreSQL, MySQL) — production-ready СУБД
- Кэширование (Redis, Memcached) — для повышения производительности
Настройка Django для production
Первым делом подготовим settings.py. Создадим разделение на локальные и production-настройки:
# settings/base.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent.parent
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME'),
'USER': os.environ.get('DB_USER'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [BASE_DIR / 'static']
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
Классическое развертывание: Gunicorn + Nginx
Шаг 1: Подготовка сервера
Для примера возьмём Ubuntu 24.04 LTS и совместимые версии Django/Python. При выборе VPS можно сравнить Timeweb Cloud (партнёрская ссылка) с другими провайдерами по ресурсам, цене и бэкапам. Перед изменениями проверь SSH и консоль восстановления. Все yourproject/yourdomain ниже замени реальными именами; выбери классический или Docker-сценарий, не запускай оба на одних портах.
ssh user@your_server_ip
sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip python3-venv nginx postgresql postgresql-contrib git libpq-dev python3-dev build-essential
Шаг 2: Настройка PostgreSQL
sudo -u postgres psql
В открытой psql-консоли создай роль и базу с владельцем; пароль введи интерактивно через \password:
CREATE ROLE youruser LOGIN;
\password youruser
CREATE DATABASE yourdbname OWNER youruser;
\qШаг 3: Развертывание приложения
Клонируем проект от пользователя развёртывания. Создай /etc/yourproject.env (root:root,600) с DJANGO_SECRET_KEY (уникальный случайный секрет), DB_NAME=yourdbname, DB_USER=youruser, DB_PASSWORD, DB_HOST=127.0.0.1 и DJANGO_SETTINGS_MODULE=yourproject.settings.base. Файл имеет формат KEY=value, без shell-команд; секреты не коммить. Проверь requirements.txt: нужны Gunicorn и совместимый PostgreSQL-драйвер. Пример ниже предполагает, что manage.py лежит в /var/www/yourproject, а пакет настроек — yourproject/settings/base.py.
sudo install -d -o "$USER" -g www-data -m 0755 /var/www/yourproject
cd /var/www/yourproject
git clone https://github.com/yourusername/yourproject.git .
python3 -m venv venv
venv/bin/pip install -r requirements.txt
# Секретный env загружается systemd, не исполняется shell:
sudo systemd-run --wait --pipe --collect -p WorkingDirectory=/var/www/yourproject -p EnvironmentFile=/etc/yourproject.env /var/www/yourproject/venv/bin/python manage.py check --deploy
sudo systemd-run --wait --pipe --collect -p WorkingDirectory=/var/www/yourproject -p EnvironmentFile=/etc/yourproject.env /var/www/yourproject/venv/bin/python manage.py migrate
sudo systemd-run --wait --pipe --collect -p WorkingDirectory=/var/www/yourproject -p EnvironmentFile=/etc/yourproject.env /var/www/yourproject/venv/bin/python manage.py collectstatic --noinput
sudo systemd-run --wait --pty --collect -p WorkingDirectory=/var/www/yourproject -p EnvironmentFile=/etc/yourproject.env /var/www/yourproject/venv/bin/python manage.py createsuperuser
sudo install -d -o www-data -g www-data -m 0750 /var/www/yourproject/media
# Код и статика доступны www-data на чтение; запись только в media.
sudo chgrp -R www-data /var/www/yourproject
sudo chmod -R g+rX /var/www/yourproject
Шаг 4: Настройка Gunicorn
Сохрани следующий unit как /etc/systemd/system/gunicorn.service для автоматического запуска:
[Unit]
Description=Gunicorn for Django
After=network.target postgresql.service
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/yourproject
EnvironmentFile=/etc/yourproject.env
RuntimeDirectory=gunicorn
RuntimeDirectoryMode=0750
UMask=0007
ExecStart=/var/www/yourproject/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn/gunicorn.sock yourproject.wsgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn # Проверяем статус
Шаг 5: Настройка Nginx
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
location /static/ { alias /var/www/yourproject/staticfiles/; }
location /media/ { alias /var/www/yourproject/media/; }
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn/gunicorn.sock;
}
}
sudo ln -s /etc/nginx/sites-available/yourproject /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Развертывание web приложения Django с помощью Docker
Docker упрощает процесс развертывания web приложения Django, обеспечивая консистентность окружения. Ниже базовый Compose-стек за локальным HTTP-портом8080. До внешнего production-доступа нужен HTTPS reverse proxy на хосте или балансировщике; публикация443 сама по себе сертификат не создаёт. Установи Docker Engine и Compose plugin по официальной инструкции для Ubuntu.
Dockerfile для Django
FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "yourproject.wsgi:application"]
Добавь в .dockerignore файлы .env, venv, .git и локальные бэкапы. В .env с правами600 задай DB_NAME, DB_USER, DB_PASSWORD и DJANGO_SECRET_KEY; используй отдельные случайные секреты. Этот файл нужен Compose и не должен попадать в образ. Docker-пример — локальный учебный bootstrap: POSTGRES_USER официального образа создаёт суперпользователя БД. До production создай отдельную роль приложения с минимальными правами, передай её DB_USER/DB_PASSWORD контейнеру web отдельно от учётных данных инициализации PostgreSQL и проверь миграции; не оставляй приложение под суперпользователем. Для production закрепи проверенные теги/дигесты образов и зависимости; postgres15 нельзя менять на другую major-версию без миграции данных.
docker-compose.yml
services:
db:
image: postgres:15
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${DB_NAME:?Set DB_NAME}
POSTGRES_USER: ${DB_USER:?Set DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 10
web:
build: .
restart: unless-stopped
volumes:
- static_volume:/app/staticfiles
- media_volume:/app/media
environment:
DJANGO_SETTINGS_MODULE: yourproject.settings.base
DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY:?Set DJANGO_SECRET_KEY}
DB_HOST: db
DB_NAME: ${DB_NAME:?Set DB_NAME}
DB_USER: ${DB_USER:?Set DB_USER}
DB_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD}
depends_on:
db:
condition: service_healthy
nginx:
image: nginx:stable-alpine
restart: unless-stopped
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- static_volume:/static:ro
- media_volume:/media:ro
ports:
- "127.0.0.1:8080:80"
depends_on:
- web
volumes:
postgres_data:
static_volume:
media_volume:
Nginx конфигурация для Docker
events {}
http {
include /etc/nginx/mime.types;
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location /static/ { alias /static/; }
location /media/ { alias /media/; }
location / {
proxy_pass http://web:8000;
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;
}
}
}
Сначала создай .env, проверь конфигурацию, выполни миграции и сборку статики один раз, затем запусти сервисы. Перед миграцией существующей базы сделай проверенный бэкап. Число workers и права runtime-пользователя настрой под приложение; пример Dockerfile не выполняет отдельное снижение привилегий.
sudo docker compose config --quiet
sudo docker compose build
sudo docker compose up -d db
sudo docker compose run --rm web python manage.py check --deploy
sudo docker compose run --rm web python manage.py migrate
sudo docker compose run --rm web python manage.py collectstatic --noinput
sudo docker compose up -d
sudo docker compose logs --tail=100
curl -H 'Host: yourdomain.com' http://127.0.0.1:8080/
Сравнение методов развертывания
| Критерий | Классическое (Gunicorn+Nginx) | Docker-развертывание |
|---|---|---|
| Сложность настройки | Средняя/Высокая | Низкая/Средняя |
| Переносимость | Низкая | Высокая |
| Масштабируемость | Сложная | Простая |
| Производительность | Высокая | Высокая (минимальные накладные расходы) |
| Идеально для | Дедицированных серверов, production | Разработки, микросервисов, CI/CD |
Частые вопросы (FAQ)
Какой способ развертывания Django выбрать новичку?
Начни с классического способа (Gunicorn + Nginx) на виртуальном сервере. Это даст понимание, как все работает "под капотом". После освоения переходи к Docker для упрощения процессов.
Нужно ли использовать Docker в production?
Docker можно использовать в production, но он не обязателен. Нужны корректный WSGI/ASGI-сервер, HTTPS, секреты, права, бэкапы и обновления. Пример Compose здесь даёт локальный HTTP-стек; внешний TLS и настройки доверенного proxy нужно завершить отдельно.
Как настроить SSL/HTTPS для Django?
Для Nginx на хосте настрой домен/DNS, установи Certbot и получи сертификат, затем проверь HTTP→HTTPS. Для Docker локальный8080 должен стоять за TLS-proxy; согласуй передачу X-Forwarded-Proto на каждом доверенном hop. В Django настрой SECURE_PROXY_SSL_HEADER только если proxy удаляет поддельный входной заголовок и задаёт его сам, затем secure cookies и HTTPS redirect. Не включай доверие к произвольному клиентскому заголовку; проверь check --deploy, вход и CSRF.
Как организовать деплой новых версий приложения?
Создай скрипт деплоя или используй CI/CD (GitHub Actions, GitLab CI). Перед обновлением сохрани базу и media, проверь восстановление и совместимость миграций. Типичный процесс: проверенная версия кода/зависимостей, миграции, сборка статики, перезапуск Gunicorn и smoke-тест. Откат кода не всегда откатывает схему базы.
Заключение
Мы рассмотрели два основных подхода к развертыванию Django. Классический метод дает полный контроль и понимание архитектуры, а Docker-подход обеспечивает современный, переносимый и масштабируемый способ деплоя.
- Используйте переменные окружения для секретов
- Настраивайте мониторинг (Sentry для ошибок, Prometheus для метрик)
- Регулярно делайте бэкапы базы данных и media, защищайте секреты и проверяйте восстановление
- Тестируйте процесс деплоя на staging-окружении
Теперь у тебя есть полное руководство для успешного развертывания Django на сервере. Начни с простого варианта, поэкспериментируй, и скоро процесс деплоя станет для тебя рутинной, но важной частью разработки.