Slim images for postgres, storage, and edge-runtime must be interchangeable with the live docker.io pin for leftover named volumes and CLI-shaped start. Numbers are never committed here — they are generated from the pin at image-build time.
Each identity-contract service sets SOURCE_IMAGE_DIGEST and
IDENTITY_SOURCE_TAG in recipe.env. UPSTREAM_IMAGE uses
${VERSION:-$SOURCE_REF} so pin selection follows the released tag
(release CI sets VERSION and overwrites SOURCE_REF). The digest
belongs to IDENTITY_SOURCE_TAG, not to SOURCE_REF. Introspection,
image build, and smokes pull tag@digest. A missing digest or a failed
pull is a hard error. When the image tag is not IDENTITY_SOURCE_TAG,
that tag's index digest is resolved — the committed digest is not reused
across versions. There is no ECR-first fallback.
SKIP_UPSTREAM_IDENTITY=1 is rejected for identity-contract image builds
and image smokes. Never invent uid/gid/mode as a substitute for the pin.
Storage /mnt is the one exception: invent 0:0:755 only when the path
is absent and the pin starts as root. If the path exists but stat
failed, fail. A test -e status other than 0 or 1 is a probe failure,
not "absent".
scripts/introspect-upstream-identity.sh (and scripts/identity-lib.sh)
pull the digest, then probe the pin:
Config.User(empty means root).- Owner/mode of the CLI mount path on the image filesystem (
statvia a bind-mounted busybox so the pin does not need a shell). - The
/etc/passwd//etc/grouplines for that owner.
Those values become Docker ARGs. scripts/render-dockerfile.sh stays
append-only for runtime.env — it does not rewrite COPY --chown.
- Start user matches the pin. Empty
Config.User,0, androotare the same (euid 0): docker.io leaves USER unset; distroless's root variant bakesUSER 0. - postgres starts as root, then drops to the probed owner before
postgresexecs.docker-entrypoint.shis the imageENTRYPOINTand follows official argv rules: empty / leading-stays the server path (postgres -D /etc/postgresql); any other argv isexec'd as-is sodb dump/db pull(bash -c) do not initdb. First boot runs/docker-entrypoint-initdb.d(.sh/.sql) in the temp-server window after bundle initdb. Always run bundlemigrate.shfirst (roles + extensions); then the CLI--from-backuprestore ininitdb.d. Hide/etc/postgresql.schema.sqlduring the bundle pass wheninitdb.d/migrate.shis the CLI restore (root copies the contents aside, truncates the inode, and chowns the copy — nomvafter drop, and sticky/tmponly lets the owner unlink). Both would run the unconditionalCREATE DATABASE _supabase. A realdb dump --localhas noCREATE ROLEand assumesextensionsexists.--help/--versionexec postgres directly (no initdb). A non-zero sourced or exec'd*.shstops the temp server and exits 1 — do not start postgres. The shim uses busybox-su, not extracted upstreamgosu. Cluster files stay inPGDATA./etc/postgresql/postgresql.confsetsdata_directory/hba_file/ident_fileatPGDATA, includes the bundle recipe (not leftover initdb conf), overridesunix_socket_directoriesto/run/postgresql,/tmp(nativelocal-dev.confstays/tmponly), and stays root-writable for CLI>>/>writes. Create/run/postgresqlat start (/runis often tmpfs) and chown it to the drop-to uid. - storage and edge-runtime stay root. Seed
/mntand/rootfrom the probe. Shipwget(storage) andsh(edge-runtime) unconditionally because the CLI always uses them. Storage shipsdist/scripts/migrate-call.js(third Rolldown input) pluspostgres-migrations'0_create-migrations-table.sqlbeside that script. EmptyENTRYPOINTandCMD ["/node/bin/node","dist/start/server.js"]so defaultdocker runstill serves, whiledocker run IMAGE node dist/scripts/migrate-call.jsis the CLI one-shot (nodeis onPATH). A nodeENTRYPOINTwould turn that argv intonode node ….
Do not extract upstream docker-entrypoint.sh or gosu. Do not root a
stateless service that the pin does not start as root.
Pairwise image smokes pull the same digest the build used. They fail
closed on pull miss. They assert identity (USER + mount owner/mode),
leftover volumes in both directions, and a CLI-shaped start for postgres
(docker-entrypoint.sh postgres -D /etc/postgresql, plus an initdb.d
marker, a --from-backup overwrite of initdb.d/migrate.sh plus
/etc/postgresql.schema.sql that must run after bundle migrate without
double-creating _supabase, a failed init script that must not start
postgres, --version that must not initdb, default-socket psql with
no -h, and a foreign-argv id that must not initdb).
Storage leftover also checks that the imgproxy pin's Config.User can
read objects on /mnt. Edge leftover write/read of /root runs inside
the pin (run_in_pin with the named volume mounted). Static busybox is
only that container's entrypoint when the pin has no shell — not a
separate image.