Ресайз изображений на лету с помощью Nginx
Иногда, когда вы создаете какой то сайт, вам требуется отображать картинки разных размеров в разных местах. Для этого вам приходится делать какой то функционал который либо в фоне, либо при первом запросе, либо еще хуже, при загрузке создает картинку в нужном размере и показывает пользователю.
Если ваш сайт на PHP то вам необходимо ставить дополнительные библиотеки, например ImageMagic или GD, и создавать дополнительную нагрузку на PHP
Но есть более элегантное решение. Так как Nginx обычно отвечает за отдачу статики, то и менять размеры картинок можно поручить ему.
Для этого уже есть готовый модуль, давайте попробуем его настроить.
Для того что бы все завелось мне пришлось добавить новый репозиторий в список
echo 'deb http://nginx.org/packages/ubuntu/ jammy nginx' | sudo tee -a /etc/apt/sources.list
У меня версию Ubuntu jammy, вам нужно указать свою версию из доступных здесь
Узнать вашу версию можно так
lsb_release -c
Дальше нужно добавить ключ к репозиторию
wget https://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key
Ну и дальше, обновляем информацию о репозиториях и устанавливаем плагин
sudo apt-get update sudo apt-get install nginx-module-image-filter
Настройка
Когда все установлено, нужно подключить плагин и настроить правила ресайза.
Редактируем конфиг
sudo vim /etc/nginx/nginx.conf
И добавляем, где нибудь в самом верху, загрузку плагина
load_module modules/ngx_http_image_filter_module.so;
Например так
worker_processes auto; load_module modules/ngx_http_image_filter_module.so; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; events { worker_connections 1024; } http {
Проверяем что все работает
sudo nginx -t
Если ошибок нет, то идем настраивать дальше. Если есть, то читаем что за ошибки, и идем гуглить или спрашивать в комментариях.
Ниже сильно упрощенный вариант конфигурационого файла /etc/nginx/sites-enabled/example.ru
server{ listen 80; root /var/www/; index index.php; server_name example.ru; location / { rewrite ^/(.*)/$ /$1 permanent; try_files $uri $uri/ /index.php?$query_string; } #image resize for location example /resize/200x300/user/avatar.jpg location ~* ^/resize/(?<width>[\d-]+)x(?<height>[\d-]+)/(?<image>.*)$ { expires max; add_header X-my-header $image; # Proxy to internal image resizing server. proxy_pass http://127.0.0.1:81/$image?width=$width&height=$height; proxy_cache images_cache; proxy_cache_valid 200 500h; } } proxy_cache_path /tmp/nginx-image-cache levels=1:2 keys_zone=images_cache:10m inactive=500h max_size=1000m; limit_req_zone $binary_remote_addr zone=30persec:32k rate=30r/s; server { # Internal image resizing server. listen 81; allow 127.0.0.1; deny all; limit_req zone=30persec burst=60; location / { alias /var/www/upload/; image_filter resize $arg_width $arg_height; image_filter_jpeg_quality 85; image_filter_buffer 10M; error_page 404 = /empty; } location = /empty { alias /var/www/upload/empty.png; } }
То есть, мы описали еще один сервер который слушает порт 81, и перенаправляем туда весь трафик попадающий под паттерн нашего пути к картинке.
Если такой картинки нет, то отдаем заранее подготовленную пустую.
Так же здесь можно поиграться с качеством картинки, что способствует ускорению загрузки сайта.
Проверяем что правило работает нормально
sudo nginx -t
И обновляем конфигурацию
sudo /etc/init.d/nginx reload
теперь при запросе картинки /var/www/upload/avatar.jpg вы можете получать эту картинку разного размера следующими способави
— example.ru/resize/200×300/avatar.jpg
— example.ru/resize/200x-/avatar.jpg
— example.ru/resize/-x300/avatar.jpg
Надеюсь материал был полезен. Если что то не работает, задавайте вопросы в комментариях.