- добавлена сборка Caddy с Souin, Otter и NutsDB - добавлена конфигурация dev, prod и test Docker Compose - настроено кеширование через Otter L1 и NutsDB L2 - добавлены e2e-тесты Bun для кеша, restart и purge - добавлена документация по запуску, API кеша и тестам
4.1 KiB
4.1 KiB
Обзор проекта
Что это
Image Gateway — self-hosted сервер для обработки и кеширования изображений. Принимает URL оригинального изображения, изменяет размер/формат/качество по запросу, кеширует результат и отдаёт быстро.
Зачем
- Оптимизация изображений — автоматический resize, crop, конвертация в WebP/AVIF
- Кеширование — однократная обработка, последующие запросы отдаются из кеша за ~1ms
- Самостоятельный хостинг — нет зависимости от внешних SaaS-сервисов (Cloudinary, imgix и т.д.)
- Простая интеграция — URL-based API, совместимое с
next/image,<img>и любым HTTP-клиентом
Архитектура
Клиент → Caddy (:8888)
├─ HIT: отдаёт из кеша (~1ms)
└─ MISS: → imgproxy → скачивает оригинал → обработка → ответ + кеширование
Компоненты
| Компонент | Роль |
|---|---|
| Caddy | Reverse proxy, кеширование (Souin plugin), HTTPS |
| imgproxy | Обработка изображений (resize, crop, конвертация форматов, качество) |
Маршрутизация
Caddy (:8888)
├─ /* → imgproxy (через кеш Souin)
└─ /souin-api/* → Souin API (управление кешем)
Возможности
Обработка изображений (imgproxy)
- Resize — вписать (
fit), заполнить (fill), точный размер (force) - Crop — обрезка с указанием ширины/высоты
- Конвертация форматов — JPEG, PNG, WebP, AVIF, GIF
- Качество — от 1 до 100
- Гравитация —
ce(центр),no(север),ea(восток), и т.д. - Подпись URL — HMAC-SHA256 для защиты от несанкционированного использования
- Whitelist доменов — ограничение источников изображений через
IMGPROXY_ALLOWED_SOURCES
Кеширование (Souin)
- Кеширует обработанные изображения в памяти
- TTL по умолчанию — 1 год (определяется
Cache-Controlот imgproxy) - HTTP-заголовок
Cache-Statusв каждом ответе —hitилиmiss - API для программного сброса кеша (
/souin-api/souin/)
Режимы работы
| Режим | Описание | Защита |
|---|---|---|
| Unsigned | URL с префиксом /unsafe/ |
Whitelist доменов (IMGPROXY_ALLOWED_SOURCES) |
| Signed | URL с HMAC-SHA256 подписью | Подпись + whitelist |
Unsigned режим рекомендуется для SPA-приложений — ключи подписи не утекают в браузер.
Интеграция
HTML
<img src="http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg" />
Next.js (loader)
const imageGatewayLoader = ({ src, width, quality }) => {
const q = quality ?? 80
return `http://localhost:8888/unsafe/resize:fit:${width}:0:0/q:${q}/plain/${src}`
}
Любой HTTP-клиент
GET http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg
Что НЕ входит в проект
- Админ-панель — реализуется как внешний сервис (Next.js, SPA и т.д.)
- Хранилище оригиналов — проект только обрабатывает изображения по URL
- CDN-слой — проект работает за CDN или напрямую