A tag is a moving pointer, so php:8.2-fpm in a Dockerfile is a build that is reproducible until the day it is not.
FROM php:8.2-fpm@sha256:a4c8f9e2b1d7...
# the day it mattered: a patch release changed the default
# value of one INI setting, and a build from the same commit
# produced a container that behaved differently from the one
# running in production.
# and the maintenance this creates:
# a bot that opens a PR when the digest moves
# a human who reads what changed
Pinning by digest turns an invisible change into a reviewable one, and the cost is that somebody has to do the reviewing — an unattended bump is the tag again with extra steps. The compromise that worked was pinning the base image by digest and letting the package manager float within it, on the grounds that a distribution security update is what we want automatically and a runtime change is not.