diff --git a/.env.example b/.env.example index ef12219..9c9c19d 100644 --- a/.env.example +++ b/.env.example @@ -92,9 +92,10 @@ THUMB_WIDTH=160 THUMB_HEIGHT=160 PREVIEW_WIDTH=1920 PREVIEW_HEIGHT=1080 -# Largest source image (in pixels, width×height) decoded to build a thumbnail or -# preview; bigger images get a placeholder. Bounds a decompression bomb and the -# per-image RAM cost. Default ~300 Mpx (e.g. 13000×17000). +# Pixel cap (width×height) for the pure-Go fallback decoder, used only when +# vipsthumbnail is NOT installed; larger images then get a placeholder. With vips +# present (the default image) thumbnails shrink on load, so this limit — and its +# RAM cost — don't apply. Also bounds a decompression bomb. Default ~300 Mpx. THUMB_MAX_PIXELS=300000000 # How many thumbnails/previews may be generated at once. Each resize already uses # every core, so a burst of large images otherwise pegs the CPU and RAM. 0 = auto diff --git a/Dockerfile b/Dockerfile index 0094748..8d6c706 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,23 +41,25 @@ RUN go mod download COPY backend/ ./ -# CGO is disabled: image processing is pure Go (disintegration/imaging) and -# video thumbnails shell out to the ffmpeg binary at runtime, so the resulting -# binary is fully static and portable across base images. +# CGO is disabled: the binary shells out to external tools at runtime +# (vipsthumbnail for image thumbnails, ffmpeg for video frames, exiftool for +# metadata) and falls back to pure-Go image processing (disintegration/imaging) +# when vips is absent, so it stays fully static and portable across base images. RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server # ----------------------------------------------------------------------------- # Stage 3 — minimal runtime # -# Alpine (not distroless/scratch) because video thumbnailing invokes ffmpeg and -# metadata extraction invokes exiftool as external processes; both must be -# present on the runtime image. +# Alpine (not distroless/scratch) because thumbnailing and metadata extraction +# invoke external processes (vipsthumbnail, ffmpeg, exiftool) that must be present +# on the runtime image. # ----------------------------------------------------------------------------- FROM alpine:3.21 AS runtime -# ffmpeg: video frame extraction. exiftool: rich image/video/audio metadata. +# vips-tools: fast, low-memory image thumbnails (shrink-on-load, so multi-hundred- +# Mpx photos cost little). ffmpeg: video frame extraction. exiftool: rich metadata. # ca-certificates/tzdata: TLS + time zones. -RUN apk add --no-cache ffmpeg exiftool ca-certificates tzdata +RUN apk add --no-cache vips-tools ffmpeg exiftool ca-certificates tzdata # Run as an unprivileged user. RUN addgroup -S -g 42776 tanabata && adduser -S -G tanabata -u 42776 tanabata