Use a small, trusted base image, scan every image, pin versions and rebuild often.
1. Start from a trusted, minimal base. Use an official image or a Docker Official Image, in a slim variant. A slim image has fewer packages, so it has fewer vulnerabilities to patch.
2. Scan images. Scan them in CI and in the registry with a tool like Docker Scout (docker scout cves <image>). Make the build fail on serious findings that already have a fix.
3. Pin versions. Pinning makes builds reproducible: the same Dockerfile gives the same image. You can pin in two ways:
- A specific tag, like
node:22.11-slim. - A digest (the image's content hash), which never changes, so the image is fully immutable.
4. Rebuild regularly. Pinning means you won't get fixes automatically. So rebuild often to pick up patched base images and dependencies. Ideally, an automated update tool opens pull requests for you.
5. Lock dependencies. Commit the lock file and use npm ci. Then the dependency versions are exactly the ones that were reviewed.
- Use minimal, trusted base images.
- Scan images in CI, for example with docker scout cves.
- Pin tags or digests so builds are reproducible.
- Rebuild regularly to pick up security patches.