Гид по технологиям

Django: хранение статических и медиа‑файлов в AWS S3

8 min read Django Обновлено 09 Apr 2026
Django: хранение статики и медиа в AWS S3
Django: хранение статики и медиа в AWS S3

логотипы Django и AWS S3

Зачем использовать S3 для статических и медиа‑файлов

Коротко: в режиме разработки Django сам обслуживает статические файлы и медиа, но в продакшне это не масштабируется. S3 позволяет:

  • разгрузить веб‑сервер и уменьшить сетевую нагрузку;
  • обеспечить высокую доступность и скорость доставки (особенно в связке с CDN);
  • упростить хранение больших файлов (аудио, видео, архивы);
  • централизовать бэкапы и политики версии/жизни объектов.

Определение: S3 — сервис объектного хранения от AWS, доступный по HTTP(S) и оптимизированный для хранения больших, редко изменяющихся объектов.

Основные сценарии использования

  • Хранение user‑upload (изображения, документы, медиа).
  • Раздача статических ассетов сайта (JS/CSS/шрифты) через S3 + CloudFront.
  • Хранение резервных копий артефактов и дампов.

Что понадобится заранее

  • Аккаунт в AWS;
  • Доступ к консоли AWS (создание S3 и IAM);
  • Проект Django с виртуальным окружением;
  • Базовые навыки командной строки и работы с settings.py.

Шаг 1: Создайте аккаунт AWS

Если у вас ещё нет аккаунта — зарегистрируйтесь на aws.amazon.com. Новые аккаунты обычно получают бесплатный доступ к 5 ГБ S3 Standard в рамках Free Tier в течение первого года. Это удобно для тестирования, но не рассчитывайте на это для продакшн‑нагрузок.

Шаг 2: Создайте S3‑бакет для проекта

  1. В консоли AWS найдите сервис S3 и откройте его.

Стартовая страница AWS

  1. Нажмите Create bucket (Создать бакет). Следуйте форме создания.

Страница создания S3‑бакета

  1. Придумайте глобально уникальное имя бакета. В большинстве случаев можно оставить остальные настройки по умолчанию.

Форма создания S3‑бакета

  1. Блокировка публичного доступа: если вы планируете открыто раздавать статику через S3 — снимите опцию “Block all public access” (Блокировать весь публичный доступ) и подтвердите предупреждение. Если используете CloudFront + OAI/Origin Access Identity или приватный доступ — оставьте блокировки и настраивайте политики доступа более тонко.

Опция публичного доступа к бакету

  1. Нажмите Create bucket. В консоли появится список ваших бакетов.

Список созданных S3‑бакетов

Важно: имя бакета глобально уникально в пределах AWS; выбирайте понятное имя (например, myproject‑static‑prod). Для тестовых бакетов добавляйте суффиксы dev/stage.

Шаг 3: Создайте IAM‑пользователя для Django

Лучше не использовать root‑учётную запись. Создайте отдельного IAM‑пользователя, которому выдайте минимальные права для работы с нужным бакетом.

  1. В консоли AWS найдите IAM.

Результаты поиска IAM

  1. В разделе Users нажмите Add users.

Интерфейс создания IAM‑пользователя

  1. Введите имя пользователя, например django‑service, и на шаге Permissions выберите Attach policies directly. Не давайте широкие права S3FullAccess на всё — лучше использовать тонкую политику, ограниченную конкретным бакетом. Для простоты разработки можно временно выбрать S3FullAccess, но в продакшне используйте политику, ограниченную ARN вашего бакета.

Форма ввода имени IAM‑пользователя

  1. На шаге Permissions найдите S3FullAccess (либо создайте кастомную политику) и присоедините её. Затем Create user.

Выбор политики доступа для IAM‑пользователя

  1. Проверьте созданного пользователя.

Страница обзора созданного IAM‑пользователя

Рекомендация: в продакшне создайте политику вида: позволить Get/Put/Delete только для префикса бакета myproject/* и только нужные операции.

Шаг 4: Создайте ключ доступа для IAM‑пользователя

Чтобы Django мог программно обращаться к S3, вам нужны Access Key ID и Secret Access Key.

  1. Откройте пользователя в IAM и вкладку Security credentials.

Список IAM‑пользователей

  1. В разделе Access keys нажмите Create access key.

Создание Access key

  1. Выберите use case (например, Local code) — это просто подсказка для AWS, не влияет на ключ.

Рекомендации по использованию Access key

  1. Дайте понятное описание и создайте ключ. Скачайте CSV или сохраните значения в безопасном месте — секретный ключ показывается только один раз.

Просмотр созданных Access key

  1. Храните ключи в переменных окружения или в менеджере секретов; не коммитите их в репозиторий.

Пример сохранения пар ключей

Шаг 5: Подключите S3 в ваш Django‑проект

Пакеты, которые понадобятся:

pip install django-storages boto3

Добавьте в INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    'storages',
]

Ключевая часть — настройки в settings.py. Рекомендуется читать значения из переменных окружения (например через os.environ или django‑environ) вместо хранения ключей в коде.

Пример корректной и безопасной конфигурации (рекомендуется для большинства случаев):

# Используйте environ/отдельные переменные среды в реальном проекте
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_REGION_NAME = os.environ.get('AWS_S3_REGION_NAME')  # например, 'eu-central-1'
AWS_S3_SIGNATURE_VERSION = 's3v4'
AWS_S3_ADDRESSING_STYLE = 'virtual'  # 'virtual' или 'path'
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
AWS_S3_VERIFY = True
AWS_QUERYSTRING_EXPIRE = 3600  # время жизни подписанных URL, сек

# Для статики
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_LOCATION = 'static'
STATIC_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_S3_REGION_NAME}.amazonaws.com/{AWS_LOCATION}/'

# Для пользовательских файлов (media)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.{AWS_S3_REGION_NAME}.amazonaws.com/media/'

# При использовании CloudFront указывайте кастомный домен в AWS_S3_CUSTOM_DOMAIN
# AWS_S3_CUSTOM_DOMAIN = 'd111111abcdef8.cloudfront.net'

Пояснения:

  • AWS_S3_SIGNATURE_VERSION = ‘s3v4’ — современный и безопасный алгоритм подписи;
  • AWS_DEFAULT_ACL = None — отключает автоматическое назначение публичного ACL при загрузке;
  • AWS_S3_FILE_OVERWRITE = False — предотвращает перезапись файлов с одинаковыми именами (Django добавит суффикс);
  • STATICFILES_STORAGE и DEFAULT_FILE_STORAGE могут быть настроены отдельно (часто медиа в префиксе “media/“, статика в “static/“).

Если вы хотите, чтобы статические файлы и медиа хранились в разных префиксах или бакетах, создайте отдельные классы storage с разными опциями.

Шаг 6: Тестируйте конфигурацию загрузки

Пример модели с ImageField (в админке или форме загрузки):

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=225)
    content = models.TextField('Post Body')
    author = models.CharField(max_length=225)
    date_published = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='posts')

    def __str__(self):
        return self.title
  1. Сделайте миграции и зарегистрируйте модель в admin.
  2. В админке создайте запись с загрузкой изображения.
  3. После успешной загрузки перейдите на страницу файла: адрес в браузере должен указывать на ваш бакет S3.

Django admin по умолчанию

Если всё настроено верно, URL изображения будет ссылаться на S3:

Изображение, загруженное в S3

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

S3 бакет с загруженной папкой

Шаг 7: Соберите статические файлы в S3

Добавьте в settings.py параметры для статики (если ещё не указали):

STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_LOCATION = 'static'

Затем выполните в окружении с правильными переменными среды:

python manage.py collectstatic --noinput

В бакете появится папка static (или другой префикс, указанный в AWS_LOCATION).

S3 бакет с папкой static

Отладка и общие проблемы

  • Ошибка 403 при доступе к объекту: проверьте ACL и политику бакета. Если используете приватный бакет и CloudFront, настройте Origin Access Identity.
  • Файлы не появляются при collectstatic: убедитесь, что переменные окружения доступны в процессе запуска команды.
  • Некорректные URL статики: проверьте STATIC_URL и AWS_S3_CUSTOM_DOMAIN.
  • Секретные ключи попали в репозиторий: немедленно замените ключи и удалите из истории Git (git filter‑repo или BFG).

Когда S3 не подходит (контрпример)

  • Низкая задержка чтения критична (реальные 100% локальные файловые операции) — локальное хранилище быстрее для коротких операций.
  • Очень частые мелкие операции записи/удаления — S3 имеет модель eventual consistency для некоторых операций; в таких сценариях лучше использовать специализированные базы данных/файловые системы.
  • Строгие требования по стоимости: при большом количестве мелких запросов стоимость запросов может превысить выгоду от хранения данных.

Альтернативы

  • Google Cloud Storage или Azure Blob Storage — API и концепции схожи;
  • Self‑hosted объектные хранилища: MinIO — совместим с S3 API, подходит для приватных облаков;
  • CDN‑only для статичных сайтов (если нет медиа‑загрузок).

Модель принятия решения (эвристика)

Используйте S3, если выполняются хотя бы два из трёх условий:

  1. Необходима высокая доступность и отказоустойчивость;
  2. Ожидается рост числа пользователей и объёмов файлов;
  3. Необходима простая интеграция с CDN и другими сервисами облака.

Если все три пункта не выполняются — рассмотрите simpler подходы.

Мини‑методология внедрения (шаг за шагом)

  1. Создать тестовый бакет и IAM с минимальными правами;
  2. Настроить проект в staging с переменными окружения;
  3. Запустить тестовые загрузки/collectstatic и провести нагрузочное тестирование;
  4. Перенести domain/CloudFront по необходимости;
  5. Перейти в продакшн, мониторить S3 метрики и расходы.

Роль‑ориентированные чек‑листы

Разработчик:

  • Установил django‑storages и boto3;
  • Добавил storages в INSTALLED_APPS;
  • Настроил переменные окружения;
  • Проверил загрузку файлов через модель/формы;
  • Запустил collectstatic.

DevOps/инфраструктура:

  • Создал бакет с понятным именем;
  • Настроил политику доступа (ограничил по ARN);
  • Организовал резервное копирование и lifecycle (версионирование/переход в Glacier);
  • При необходимости настроил CloudFront и OAI.

Security/Compliance:

  • Не хранить секреты в репозитории;
  • Включить MFA для root и ключевых пользователей;
  • Настроить мониторинг и оповещения на новую активность;
  • Проверить соответствие требованиям GDPR/локальных законов.

Безопасность и соответствие (GDPR и приватность)

  • Персональные данные: если вы храните PII (изображения с лицами и т.д.), убедитесь, что доступ контролируется и шифрование на стороне сервера включено (SSE‑S3 или SSE‑KMS).
  • Логи доступа: сохраняйте аудит доступа к объектам и настройте CloudTrail для отслеживания действий IAM‑пользователей.
  • Локальные правила: при работе с данными граждан ЕС соблюдайте принципы минимизации данных и право на удаление — продумайте процессы удаления объектов в S3.

Оптимизация затрат и производительности

  • Используйте lifecycle‑политики для перевода старых объектов в более дешёвые классы хранения (Infrequent Access, Glacier).
  • Для быстрой отдачи статики используйте CloudFront (или другой CDN) с кэшированием и кастомным доменом.
  • Минимизируйте количество GET/PUT запросов: комбинируйте операции и используйте multipart upload для больших файлов.

Критерии приёмки

  • Загруженные через Django объекты появляются в S3 и доступны по корректным URL.
  • collectstatic успешно загружает все статические файлы в префикс static/ бакета.
  • В продакшне секреты вынесены в безопасное хранилище (переменные окружения, AWS Secrets Manager).
  • Права доступа ограничены минимально необходимыми для корректной работы приложения.

Шаблон политики IAM (пример ограничения доступа к конкретному бакету)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    }
  ]
}

Замените your-bucket-name на имя вашего бакета. Эта политика даёт базовые права на работу с объектами.

Тест‑кейсы и приёмка

  • Попытаться загрузить файл через админку и проверить появление в бакете;
  • Удалить файл в приложении — убедиться, что он удалён и в S3;
  • Выполнить collectstatic и проверить структуру префиксов в бакете;
  • Моделировать потерю ключа — заменить ключи и убедиться в отсутствии доступа старых ключей.

Советы по миграции существующих файлов

  • Для большого объёма файлов используйте aws cli и multipart upload.
  • Синхронизируйте корневую структуру: aws s3 sync /local/path s3://your-bucket-name/media/
  • После миграции проверьте, что URL в базе данных корректны (если хранилище URL‑зависимое).

Заключение

AWS S3 — надёжный и гибкий инструмент для хранения статического контента и пользовательских файлов в проектах Django. Правильная настройка IAM, безопасное хранение ключей и разумная архитектура (CDN, lifecycle‑политики) обеспечат масштабируемость и контролируемые затраты. Внимательно подойдите к вопросам безопасности и соответствия, а также протестируйте сценарии на staging до миграции в production.

Короткое резюме:

  • Создайте отдельный IAM с минимальными правами;
  • Используйте django‑storages + boto3 и храните креды в окружении;
  • Настройте STATICFILES_STORAGE и DEFAULT_FILE_STORAGE корректно;
  • Проведите тестирование, настройте мониторинг и lifecycle.

Важно: S3 — не универсальное решение для всех задач. Оцените частоту операций, требования к задержке и стоимость перед принятием решения.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как добавить субтитры к видео в Aegisub
Видео

Как добавить субтитры к видео в Aegisub

Как учиться программированию без стресса
Программирование

Как учиться программированию без стресса

Экспорт сканов из Apple Notes
How-to

Экспорт сканов из Apple Notes

Как использовать Android как веб‑камеру
Руководство

Как использовать Android как веб‑камеру

Таймкод в Premiere Pro: burn-in и рабочие процессы
Видео

Таймкод в Premiere Pro: burn-in и рабочие процессы

Windows 11: убрать значок Teams и новые настройки панели задач
Windows

Windows 11: убрать значок Teams и новые настройки панели задач