docker-compose.yml pulls both, so self-hosting needs no clone, no Node, and no build.
Both are public, so
docker pull needs no login.
Tags
Pin a tag with
FLOE_IMAGE_TAG:
The variable is
FLOE_IMAGE_TAG, not FLOE_VERSION. FLOE_VERSION belongs to the CLI installer and is written with a leading v, as in v1.9.1. Image tags carry no v, so reusing that name would resolve to a tag that does not exist.Pinning a digest
A tag can be repointed. A digest cannot, so it is the strongest pin:Architectures
Both images are published forlinux/amd64 and linux/arm64. Docker picks the right one automatically, so Raspberry Pi, Oracle Ampere, AWS Graviton, and Apple silicon all work with the same commands as anywhere else.
Each architecture is built and smoke-tested on its own hardware before any tag points at it, and a tag is only published once every architecture of both images has passed. A partly-built release is never visible.That matters more than it sounds. The image optimiser fails at load time rather than at build time, and when it fails it does not error: it quietly serves the original file. So a broken ARM image would look perfectly healthy to anything that only checks whether the page loads. The smoke test asserts the optimiser actually returns WebP, on real ARM.
linux/arm/v7, older Raspberry Pi models) is not published. Node dropped support for it and no prebuilt image-processing binaries exist.
Building from source
Contributors, and anyone who wants their own domain in share previews, add the build overlay:floe-server:dev and floe-client:dev, so a local build never replaces a pulled image under the same name.
Share previews and canonical links
These have to be written into the HTML when the app is built, so a shared image cannot know which domain it will be served from. Claiming one would mean every self-hosted instance advertising somebody else’s site to crawlers, so the published image emits only what is true without knowing its own origin:
To put your own domain in them, build the client yourself: