Skip to content

pin-image-version

Why FROM node or FROM node:latest breaks reproducible Docker builds, and how to pin base image tags (or digests) properly.

On this page

FROM node and FROM node:latest mean "whatever the registry serves today". The same Dockerfile produces different images on different days, so a build that passed CI last week can fail — or ship different behavior — this week without a single line changing. This rule flags any FROM that uses no tag or the latest tag.

What the rule catches

Dockerfile — floating base image
FROM node
WORKDIR /app

Scanning this file reports:

⚠ WARN [docker-doctor/pin-image-version]
  Base image 'node' does not specify a tag. This makes builds non-deterministic.

Why it matters

Unpinned bases break the core promise of a Dockerfile: reproducibility. Debugging becomes guesswork ("it works on my rebuild"), rollbacks stop being rollbacks because rebuilding an old commit pulls a new base, and you silently absorb every change the upstream image publishes — including breaking ones and, in a registry-compromise scenario, malicious ones. Pinning turns base-image updates into a reviewable diff instead of a background surprise.

How to fix it

Specify a concrete tag instead of latest or no tag (e.g., node:22.2.0-alpine instead of node).

Dockerfile — pinned tag
FROM node:22.2.0-slim
WORKDIR /app

How specific to pin is a spectrum:

  • node:22-slim — tracks patch releases automatically; fine for most apps.
  • node:22.2.0-slim — exact version; rebuilds are stable until you bump it.
  • node:22.2.0-slim@sha256:… — digest-pinned; byte-for-byte immutable, the strictest supply-chain posture.

Whichever you choose, let a bot (Renovate, Dependabot) propose the bumps so pinning doesn't decay into running years-old bases.

Rule details

  • Rule keydocker-doctor/pin-image-version
  • Category — Security
  • Default severitywarning
  • Applies to — Dockerfiles

Explain this rule from the CLI:

npx @docker-doctor/cli@latest rules explain docker-doctor/pin-image-version

Change its severity — or turn it off — in your config file:

// docker-doctor.config.ts
export default {
  rules: {
    "docker-doctor/pin-image-version": "off",
  },
};

Severity affects the health score: error findings cost more points than warning, and info costs the least.