← Назад к вопросам
Как реализовывал статику на продакшн?
2.0 Middle🔥 121 комментариев
#DevOps и инфраструктура#Django
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как реализовывал статику на продакшн
Управление статическими файлами (CSS, JS, изображения, шрифты) на production — критически важная часть развёртывания Django приложений. Разберёмся со всеми компонентами.
Проблема: Django не сервирует статику на production
Django в development режиме автоматически сервирует статические файлы через встроенный django.contrib.staticfiles. Но на production это небезопасно и неэффективно:
# development (works автоматически)
DEBUG = True # django.contrib.staticfiles слушает статику
# production (НЕ работает!)
DEBUG = False # Статика 404, если её не обслуживает nginx/apache
Шаг 1: Конфигурация Django settings
# settings/production.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# Основная конфигурация
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
# Статические файлы
STATIC_URL = '/static/' # URL по которому доступна статика
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # Где собираются файлы
# Для production с CDN
if not DEBUG:
STATIC_URL = 'https://cdn.yourdomain.com/static/' # CDN URL
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# Media файлы (загрузки пользователей)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Whitenoise для сервирования статики (если без nginx)
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware', # Добавляем первым
'django.middleware.security.SecurityMiddleware',
# ... остальное middleware
]
# Кэширование статики (1 год)
if not DEBUG:
WHITENOISE_AUTOREFRESH = False
WHITENOISE_USE_FINDERS = True
Шаг 2: Сбор статических файлов
# Локально перед деплоем
python manage.py collectstatic --noinput --clear
# Что это делает:
# 1. Находит все static файлы в приложениях
# 2. Копирует их в STATIC_ROOT
# 3. Минифицирует CSS/JS (если установлен WhiteNoise)
# 4. Создаёт manifest для кэширования
Результат структуры:
projectroot/
├── staticfiles/ # STATIC_ROOT
│ ├── admin/
│ ├── css/
│ │ ├── style.min.css
│ │ └── style.min.css.gz # Gzip версия
│ ├── js/
│ ├── images/
│ └── staticfiles.json # Manifest для хэширования
├── myapp/
│ ├── static/
│ │ ├── css/
│ │ ├── js/
│ │ └── images/
Шаг 3: Сервирование статики на production
Вариант A: С Nginx (Рекомендуется)
# /etc/nginx/sites-available/yourdomain.com
upstream django_app {
server 127.0.0.1:8000;
}
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Статические файлы
location /static/ {
alias /home/appuser/myproject/staticfiles/;
# Кэширование на 1 год для хэшированных файлов
expires 1y;
add_header Cache-Control "public, immutable";
# Gzip уже включен на уровне Nginx
}
# Media (загрузки пользователей)
location /media/ {
alias /home/appuser/myproject/media/;
expires 7d;
add_header Cache-Control "public";
}
# Django приложение
location / {
proxy_pass http://django_app;
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;
}
}
Проверка Nginx конфига:
sudo nginx -t
sudo systemctl reload nginx
Вариант B: С WhiteNoise (Простой, без Nginx)
Dля маленьких приложений или тестирования:
# settings.py
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
# ... остальное
]
# settings/production.py
if not DEBUG:
# WhiteNoise с хэшированием файлов
STATIC_URL = '/static/'
WHITENOISE_AUTOREFRESH = False
WHITENOISE_USE_FINDERS = True
WHITENOISE_MIMETYPES = {
'.webp': 'image/webp',
'.woff2': 'font/woff2',
}
Установка:
pip install whitenoise
Вариант C: С CDN (CloudFlare, AWS S3)
Для скорости и масштабируемости:
# settings/production.py
import os
if os.getenv('USE_S3') == 'True':
# AWS S3
import boto3
AWS_STORAGE_BUCKET_NAME = 'my-bucket-name'
AWS_S3_REGION_NAME = 'eu-central-1'
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/static/'
STATIC_ROOT = 'static/'
# Использование django-storages
STORAGES = {
'default': 'storages.backends.s3boto3.S3Boto3Storage',
'staticfiles': 'storages.backends.s3boto3.S3StaticStorage',
}
AWS_QUERYSTRING_AUTH = False # Публичные файлы
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
else:
# Локальная статика
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Установка:
pip install django-storages[s3]
pip install boto3
Загрузка в S3:
python manage.py collectstatic --noinput
Шаг 4: Оптимизация для production
Минификация CSS/JS
# settings/production.py
if not DEBUG:
# Минификация через WhiteNoise
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# Или если используешь webpack/gulp — просто указываешь готовые файлы
# Структура:
# static/
# ├── js/
# │ └── main.min.js
# ├── css/
# │ └── style.min.css
Хеширование файлов (Cache busting)
# settings/production.py
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
# В templates:
# {% load static %}
# <link rel="stylesheet" href="{% static 'css/style.css' %}">
# Результат: <link rel="stylesheet" href="/static/css/style.a1b2c3d4.css">
Сжатие Gzip
# nginx.conf
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1000;
gzip_comp_level 6;
Шаг 5: Deploy процесс
#!/bin/bash
# deploy.sh
set -e
echo "Pulling code..."
git pull origin main
echo "Installing dependencies..."
pip install -r requirements.txt
echo "Running migrations..."
python manage.py migrate
echo "Collecting static files..."
python manage.py collectstatic --noinput --clear
echo "Restarting service..."
sudo systemctl restart gunicorn
sudo systemctl restart nginx
echo "Deploy complete!"
Шаг 6: Проверка на production
# 1. Проверить, что статика собрана
ls -la staticfiles/
# 2. Проверить CSS в браузере
curl -I https://yourdomain.com/static/admin/css/base.css
# HTTP/1.1 200 OK
# Cache-Control: public, max-age=31536000, immutable
# 3. Проверить источник страницы
# <link rel="stylesheet" href="/static/admin/css/base.a1b2c3.css">
# 4. Проверить размер и сжатие
du -sh staticfiles/
Полный checklist
-
DEBUG = Falseв production settings -
STATIC_URLиSTATIC_ROOTправильно сконфигурированы - Запущен
python manage.py collectstatic - Nginx/Apache сконфигурирован для сервирования
/static/ - Кэширование заголовков установлено (Cache-Control, Expires)
- Gzip сжатие включено
- HTTPS используется
- CDN/S3 настроен (если нужен)
- Медиа файлы также обслуживаются
- Тестирование: всё ли работает из браузера
Типичные ошибки
# ❌ Ошибка 1: Забыл collectstatic
python manage.py runserver # static работает
# Но на production — 404!
# ✅ Решение
python manage.py collectstatic --noinput
# ❌ Ошибка 2: DEBUG = True на production
DEBUG = True # Django сервирует статику, но медленно
# ✅ Решение
DEBUG = False
# Используй Nginx для статики
# ❌ Ошибка 3: STATIC_ROOT и STATIC_URL в одной папке
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/static/' # Неправильно, если оба указывают одну папку
# ✅ Решение
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/staticfiles/' # Отдельная папка