A tag such as node:22.11-slim is a label the publisher can point at a different image at any time, and publishers routinely re-push version tags with rebuilt images. A digest (image:tag@sha256:…) identifies the exact content and cannot change. Pinning the digest makes builds reproducible and means a compromised or mistaken re-push of the tag can't change your image.
openrouting — dockerfile explainer
$ explain Dockerfile! Tagged base images have no digest (applies to every tagged … lowline 1fix: see below$
What the free Dockerfile explainer reports on the risky example below.
Why it matters
Tags are mutable. Re-pushing a version tag with OS security patches is normal, which is helpful, but it also means the same Dockerfile can produce different images, and a malicious push to the tag would be picked up by your next build.
A digest is the content hash of the image manifest. When a FROM has both a tag and a digest, the digest decides what is pulled; the tag is kept for readers.
The explainer raises this once per file (low severity), for the first tagged FROM without a digest, and the advice applies to every such FROM.
Risky and safer Dockerfile
RiskyDockerfile
FROM node:22.11-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY src ./src
USER 10001
HEALTHCHECK CMD ["node", "src/healthcheck.js"]
CMD ["node", "src/server.js"]
SaferDockerfile
FROM node:22.11-slim@sha256:<digest of the tag you tested>
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY src ./src
USER 10001
HEALTHCHECK CMD ["node", "src/healthcheck.js"]
CMD ["node", "src/server.js"]
How to fix it
Look up the digest of the tag you use, for example with docker buildx imagetools inspect node:22.11-slim.
Write it after the tag: FROM node:22.11-slim@sha256:<digest>. Use the multi-platform index digest if you build for more than one architecture.
Let Renovate or Dependabot update the digest in pull requests, so you still receive the publisher's patched rebuilds, after review.
When it's acceptable
Images where you would rather pick up the publisher's patched rebuilds of a tag automatically and accept that builds are not byte-for-byte reproducible. That is a reasonable trade-off if you have no update bot.
Check your own Dockerfile
The risky example is loaded below. Paste your own file to check it for this and every other Dockerfile rule. It runs in your browser; nothing is uploaded.
Sets the default command to node src/server.js. It runs when the container starts, and anything passed to docker run replaces it.
Questions
What is a Docker image digest?
A sha256 hash of the image manifest, written as image@sha256:…. It identifies exact content, so unlike a tag it can never point at a different image.
Do I still need the tag if I pin a Dockerfile base image by digest?
It isn't needed to pull the image, since the digest decides what is used, but keeping it (image:tag@sha256:…) tells readers and update bots which version the digest belongs to.
Won't pinning a digest stop me getting security updates?
Only if nothing updates it. Renovate and Dependabot can propose a new digest when the tag is re-pushed, so you get patched images through a reviewed pull request.