FROM node with no tag means node:latest, and latest is just a tag the publisher moves to each new release. Two builds of the same Dockerfile can start from different base images, so what you tested is not necessarily what you ship, and a major version bump or a bad upstream release reaches production without anyone reviewing it.
openrouting — dockerfile explainer
$ explain Dockerfile! Base image node is not version-pinned mediumline 1fix: see below$
What the free Dockerfile explainer reports on the risky example below.
Why it matters
latest moves whenever the publisher pushes a new release, including major versions with breaking changes. A rebuild for an unrelated fix can silently change the runtime, the OS packages and the default user under your app.
Without a version in the Dockerfile you cannot tell from the repository which base an image was built on, which makes it harder to reproduce a build or to know whether an advisory affects you.
Pinning makes base changes explicit: an update becomes a one-line diff that goes through review and CI like any other change.
Risky and safer Dockerfile
RiskyDockerfile
FROM node:latest
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
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
Replace latest (or a missing tag) with a specific version tag, e.g. node:22.11-slim.
For an immutable reference, add the digest too: node:22.11-slim@sha256:<digest>.
Let Renovate or Dependabot open pull requests for base image updates so you still get security fixes, through review.
When it's acceptable
Scratch experiments and throwaway images where reproducibility doesn't matter.
The rule skips FROM scratch, references to an earlier build stage, and image names built from an ARG, since those are pinned (or not) somewhere else.
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.
The latest tag (or no tag) can point at a different image on every build, so what you tested is not what you ship and upstream changes reach production unreviewed.
Safer: Pin a specific version tag, and ideally the digest too, e.g. image:1.27@sha256:<digest>, and let Renovate or Dependabot propose bumps.
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 does FROM image without a tag use in a Dockerfile?
It uses the latest tag. latest is not special or necessarily the newest stable release; it is whichever image the publisher last pushed under that tag.
Should I use the latest tag in production Dockerfiles?
No. Pin a version tag so builds are repeatable and base changes go through review, and ideally pin the digest as well.
How do I keep a pinned base image up to date?
Use a dependency bot such as Renovate or Dependabot, which can open a pull request when a newer tag or digest is published, so updates are deliberate and tested.