У интернет-магазина у каждого товара одна и та же картинка представлена в нескольких разрешениях. Можно ли с помощью Nginx генерировать их на лету и как оптимизировать этот процесс?

«У интернет-магазина у каждого товара одна и та же картинка представлена в нескольких разрешениях. Можно ли с помощью Nginx генерировать их на лету и как оптимизировать этот процесс?» — вопрос из категории Веб-серверы и балансировка, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, Nginx может генерировать изображения на лету с помощью официального модуля ngx_http_image_filter_module. Однако это не всегда оптимальный подход для продакшена из-за нагрузки на CPU.

Базовый пример ресайза:

location ~* ^/images/resized/(d+)x(d+)/(.+.(jpg|jpeg|png))$ {
    # $1 - ширина, $2 - высота, $3 - имя файла
    image_filter resize $1 $2;
    image_filter_buffer 10M; # Максимальный размер исходного изображения
    image_filter_jpeg_quality 85; # Качество для JPEG
    root /path/to/original/images;
    try_files /$3 =404; # Ищем оригинальный файл
}

Запрос к /images/resized/200x100/product.jpg вернет уменьшенную копию.

Критически важные методы оптимизации:

  1. Кеширование — главный инструмент. Кешируйте сгенерированные миниатюры на диске или в памяти.

    proxy_cache_path /var/cache/nginx/images levels=1:2 keys_zone=img_cache:10m inactive=30d;
    
    location ~* ^/images/resized/ {
        image_filter resize $arg_w $arg_h;
        proxy_cache img_cache;
        proxy_cache_key "$uri$is_args$args";
        proxy_cache_valid 200 30d;
        add_header X-Cache-Status $upstream_cache_status;
        # ... остальная конфигурация image_filter
    }
  2. Предварительная (offline) генерация — для фиксированного набора размеров (превью, карточка товара) генерируйте изображения один раз на этапе загрузки товара, используя библиотеки типа ImageMagick или Pillow. Nginx тогда просто отдает статику.

  3. Использование CDN — разместите сгенерированные или оригинальные изображения в CDN (CloudFront, Cloudflare). Многие CDN имеют встроенные функции ресайза "на лету" (например, Cloudflare Images, Imgix), что снимает нагрузку с вашего сервера.

  4. Оптимизация форматов — настройте отдачу современных форматов (WebP, AVIF) для поддерживающих их браузеров, используя директиву map для проверки заголовка Accept.

  5. Отказ от Nginx Image Filter в пользу специализированного сервиса — для высоких нагрузок лучше вынести обработку изображений в отдельный микросервис (на Go, Python с Pillow) или использовать облачные сервисы. Nginx в этой схеме выступает как прокси или отдает уже готовые файлы из кеша.