73 lines
3.0 KiB
Markdown
73 lines
3.0 KiB
Markdown
---
|
|
title: "TIL: resizing images on-the-fly with nginx"
|
|
date: 2023-03-22T09:46:10
|
|
slug: til-resizing-images-on-the-fly-with-nginx
|
|
|
|
---
|
|
Because I've started using Wordpress as a Markdown backend for 11ty, the 11ty image plugin no longer works, which is a bummer. So for a while I've been serving images at their default resolution which is to say, too big.
|
|
|
|
As it turns out, there's an nginx module, [image_filter](https://nginx.org/en/docs/http/ngx_http_image_filter_module.html), that can be used to resize images per request. I'm using Ubuntu, and the module doesn't exist in the standard repositories, so I followed [nginx's guide to adding their repositories](http://nginx.org/en/linux_packages.html#instructions).
|
|
|
|
After that, I ran `sudo apt update && sudo apt install nginx-module-image-filter`, and then added the following line to my nginx conf file (`/etc/nginx/nginx.conf`):
|
|
|
|
```nginx
|
|
load_module modules/ngx_http_image_filter_module.so;
|
|
```
|
|
|
|
## Serving resized images
|
|
|
|
As a baseline, I can serve resized images by just adding the `image_filter` directive to a location that matches images, e.g.:
|
|
|
|
```nginx
|
|
location ~* ^(/.+)\.(jpg|jpeg|jpe|png|gif)$ {
|
|
add_header Vary Accept;
|
|
image_filter resize 1000 -;
|
|
expires 30d;
|
|
}
|
|
```
|
|
|
|
This works, but it increases server load a fair bit, because it's now resizing every image on every single request.
|
|
|
|
## Caching the requests
|
|
|
|
So, now I need to cache my requests. I can add a separate server that I use `proxy_pass` to call. This server will serve resized images, and then I can use `proxy_cache` to cache the responses for however long I choose.
|
|
|
|
```nginx
|
|
server {
|
|
server_name localhost;
|
|
listen 8888;
|
|
|
|
location ~* ^(/.+)\.(jpg|jpeg|jpe|png|gif)$ {
|
|
root /path/to/my/images;
|
|
image_filter resize 1000 -;
|
|
}
|
|
}
|
|
|
|
proxy_cache_path /tmp/images-cache/ levels=1:2 keys_zone=images:10m inactive=24h max_size=100m;
|
|
|
|
# main server block
|
|
server {
|
|
listen 80;
|
|
location ~* ^(/.+)\.(jpg|jpeg|jpe|png|gif)$ {
|
|
add_header Vary Accept;
|
|
proxy_pass http://localhost:8888$uri;
|
|
proxy_cache images;
|
|
proxy_cache_valid 200 30d;
|
|
expires 30d;
|
|
}
|
|
|
|
location /wp-content/uploads {
|
|
# You need to explicitly define DNS resolution when using
|
|
# variables in the proxy_pass directive. This trick resolves that.
|
|
proxy_pass http://localhost:8888/;
|
|
}
|
|
}
|
|
```
|
|
|
|
So now what's happening is that any call to an image file is being proxied to a new backend running on port 8888, and caching the responses. The backend is the part responsible for serving resized images. I've put a 30-day cache on the images, but to be honest it can probably be longer because I very rarely update these.
|
|
|
|
## Next steps
|
|
|
|
This is great, and has really reduced the size of the images I'm serving, but next I'd like to have it serve webp versions of images if they exist - but that will require preprocessing the images and then attempting to serve them.
|
|
|