MediaProxy 是一个高并发、低内存的 Go HTTP(S) 反向代理,支持按需图片处理和本地磁盘缓存。源站可以是 S3、MinIO、Cloudflare R2、CDN 或任意固定 HTTP(S) 服务。
它不是开放代理:源站只来自启动配置,客户端不能通过请求参数改变 scheme、host 或 endpoint。没有 image 参数时走流式透传;有参数时 best-effort 尝试处理,任何不支持、损坏、超限或处理错误都回退源站原响应。
- 固定单源或按 Host/path 最长前缀匹配的多源路由;每条路由支持 round-robin、weighted round-robin、random 和 least-connection backend 负载均衡。
- GET/HEAD、Range、条件请求、重定向抑制、escaped path 和原始 query 保留。
- 固定回源 Host/请求头、allowlist/denylist、Cookie/Authorization 策略、环境代理开关。
Forwarded/X-Forwarded-*、可信代理 CIDR、请求 ID 和 JSON 结构化日志。- JPEG、PNG、WebP、GIF、AVIF、HEIC/HEIF 的内容探测和 libvips 处理,支持 resize、crop、rotate、flip、quality、format、EXIF orientation 和可选水印。
- 内存阈值后临时文件暂存、全局 spool budget、图片/输出/并发限制和可取消处理 semaphore。
- SHA-256 磁盘缓存、TTL/容量清理、完整性校验、singleflight 和共享目录
flock生成锁。 - Bearer token、HMAC signed URL、AWS SigV4、OAuth client credentials、源站 mTLS 和 Qiniu 参数子集兼容。
/healthz、/readyz、Prometheus/metrics、受保护 pprof、debug decision、cache purge/prewarm。- 多证书 SNI HTTPS ingress 和可选 HTTP 308 重定向。
export S3IMGPROXY_ORIGIN_URL=https://origin.example.com
export S3IMGPROXY_ADDR=:8080
./s3imgproxy请求示例:
GET /photos/a.jpg
GET /photos/a.jpg?image=v1/resize,w_300,h_300,mode_contain
GET /photos/a.jpg?image=v1/resize,w_800/format,webp/q,82
image 只由代理消费,其他 query 参数的顺序和编码保持不变。完整语法见 docs/image-parameter-v1.md。
多源使用 S3IMGPROXY_ORIGINS_JSON,例如:
[
{"name":"images","match_host":"img.example.com","path_prefix":"/","load_balance":"weighted_round_robin","backends":[{"name":"a","url":"https://s3-a.example.com/bucket","weight":2},{"name":"b","url":"https://s3-b.example.com/bucket"}]},
{"name":"private","match_host":"private.example.com","path_prefix":"/avatars","url":"https://r2.example.com/bucket"}
]HTTPS 证书使用 S3IMGPROXY_TLS_CERTIFICATES_JSON;列表支持精确 host、一级 wildcard 和默认证书。设置 S3IMGPROXY_HTTP_REDIRECT_ADDR=:80 可同时启动 HTTP 308 重定向监听。完整字段和安全注意事项见 docs/configuration.md 和 docs/deployment.md。
正式 Dockerfile 使用 digest 固定的 Go/Alpine builder、精确 libvips 版本和非 root UID 65532。缓存和暂存目录必须挂载为可写卷:
docker build --pull --build-arg VERSION=1.0.0 -t s3imgproxy:1.0.0 .
docker run --rm --read-only --tmpfs /tmp \
-v s3imgproxy-cache:/var/cache/s3imgproxy \
-v s3imgproxy-tmp:/var/lib/s3imgproxy/tmp \
-e S3IMGPROXY_ORIGIN_URL=https://origin.example.com \
-p 8080:8080 s3imgproxy:1.0.0本地示例 Compose:
docker compose up --build -d
curl -fsS http://127.0.0.1:8080/healthz所有环境变量在启动时解析、校验,修改后需要重启。敏感变量包括固定回源头、AWS secret、OAuth secret、mTLS 私钥、Bearer token、签名密钥和 admin token;它们不会写入日志或错误响应。完整类型、默认值、范围和重启要求见 docs/configuration.md。
关键资源限制:
| 变量 | 默认值 | 作用 |
|---|---|---|
S3IMGPROXY_MAX_SOURCE_BYTES |
32 MiB | 单源 body 处理上限 |
S3IMGPROXY_MAX_OUTPUT_BYTES |
64 MiB | 生成图片输出上限 |
S3IMGPROXY_MAX_SPOOL_BYTES |
256 MiB | 并发暂存总预算 |
S3IMGPROXY_MAX_PIXELS |
100,000,000 | 解压缩炸弹防护 |
S3IMGPROXY_MAX_CONCURRENCY |
4 | libvips 请求并发 |
S3IMGPROXY_PROCESS_TIMEOUT |
15s | 单请求处理超时 |
GET /healthz只表示进程存活。GET /readyz检查临时目录是否可用。GET /metrics输出 Prometheus 文本指标;配置S3IMGPROXY_ADMIN_TOKEN后需要 Bearer。- 配置 admin token 后注册
/debug/decision、POST /admin/cache/purge和POST /admin/cache/prewarm。 - 配置
S3IMGPROXY_ENABLE_PPROF=true且设置 admin token 后注册受保护 pprof。
日志为 JSON,包含 request ID、源站/暂存/处理耗时、缓存状态、回退原因和错误分类;不会记录 query、Authorization、Cookie 或签名内容。
项目最低 Go 版本为 1.23。按照项目约束,构建和测试统一在 Ubuntu SSH 虚拟机执行:
export PATH="$HOME/.local/go/bin:$PATH"
go test -mod=vendor ./...
go test -mod=vendor -tags libvips ./...
go vet -mod=vendor -tags libvips ./...
go test -mod=vendor -race ./...
go build -mod=vendor -tags libvips ./cmd/s3imgproxyParser fuzz、libvips 集成测试、Docker non-root/只读根文件系统验证和性能采样命令见 docs/fault-testing.md、docs/performance.md 和 docs/libvips.md。
无处理参数的路径不读取完整响应体;处理路径只在必要时暂存,内存超过阈值切换到私有临时文件。源站连接池复用、libvips 内部单线程、请求级并发 semaphore、singleflight、atomic cache rename 和 fail-open cache 共同控制延迟、内存和高并发下的尾部放大。
MIT,见 LICENSE。