An image that can actually render a HEIC, which took two tries

Contribution Date
Contribution Project
Contribution Details
An image that can actually render a HEIC, which took two tries Go-live item 1: something that runs somewhere other than this laptop. One image carrying `damd`, `dam-worker`, `damctl` and the media toolchain, plus the deploy order and the things it deliberately does not provide. ## Not distroless, and not three images `dam-media` does not link libvips or libavformat — it *executes* `vips`, `vipsheader`, `vipsthumbnail`, `ffmpeg` and `ffprobe` under a sandbox that clears the environment and applies rlimits. A static binary with nothing around it would start, serve the API, and fail every derivative with "no `vips` on PATH", which looks like a code bug for a day before anybody suspects the image. One image because the three binaries share the whole dependency tree and the media layer is most of the bytes. It also keeps them in lockstep: a worker running a different build from the API is very hard to see, because both look healthy while the queue quietly produces different results. ## Building it found a total failure that no test could `vipsthumbnail`'s ICC flag is `--output-profile` from vips 8.18 and `--export-profile` before it. The code hard-coded the newer name. Debian bookworm ships 8.14 and trixie ships 8.16, so on **any** Debian base every vips-rendered derivative failed with `Unknown option --output-profile`. Two things made it worse than it sounds. It is invisible for PNG and JPEG, which the pure-Rust path decodes — so an image looks fine until somebody uploads from a phone. And it is total for HEIC, which only vips can decode, so the failure lands on exactly the format a real library is full of. I moved the base from bookworm to trixie first, assuming a version bump was the fix, and watched it fail identically — which is what sent me to `vipsthumbnail --help` inside the container rather than to the release notes. The toolchain now asks the binary its version at discovery and picks the flag that build accepts. Discovery, not per render: it cannot change while the process runs, and asking per render would be a process spawn per thumbnail. An unparseable version assumes the newer spelling, deliberately — a future `--version` format should not silently downgrade every deployment to a flag that release may have dropped. Three tests: the version table, the boundary, and one that asks the *local* vips for its `--help` and asserts discovery chose a flag that appears in it. That last one passes on the pinned 8.18.5 and inside a trixie container without a cfg deciding which truth to expect. Verified where it matters: a HEIC re-rendered inside the container produced all three derivatives, and the thumbnail is 15,442 bytes of real WebP in the bucket matching the row exactly. Before the fix the same job failed twice with the same message. ## A deployment gotcha worth writing down A delivery URL is a `302` to a presigned S3 URL and the signature covers the `Host` header, so the endpoint the server signs with must be the one the browser connects to. Signing against one hostname and fetching via another returns `403 SignatureDoesNotMatch` with nothing explaining why. There is no way to configure an internal connect endpoint and a separate public signing endpoint; if the bucket is reachable under two names they have to be the same name here. Recorded in `docker/DEPLOY.md` rather than discovered in staging. ## Also corrected: three places claimed a sqlx setup that does not exist ARCHITECTURE §5.5 describes committed `.sqlx/` offline query metadata and `.mise.toml` exports `SQLX_OFFLINE=true` "so query! can resolve tenant tables". There are **zero** `query!` macros in the tree — every statement is a runtime `sqlx::query()` over a string, there is no `.sqlx/` directory, and a `COPY .sqlx/` in the Dockerfile would simply fail the build. Noted where it would mislead the next person rather than left as three mutually supporting claims about a thing that is not there. ## What the doc says the image does not do Backups, metrics, a readiness probe, rate limiting, virus scanning, TLS, and human authentication. All named in `docker/DEPLOY.md` as absent, because an image is not a deployment and the next six items on the go-live list are exactly these. `.dockerignore` excludes `target/`, which is 40+ GB of local artefacts that would otherwise be uploaded to the daemon and then ignored.
Contribution Author
Bassam Ismail
Files count
0
Patches count
1