
A Container Tag Is a Pointer, Not a Version
Key takeaway: Tags are mutable references that can be repointed at any time. Only a digest identifies a specific image, which makes digests the only basis for reproducible deployment.
Why Tags Deceive
A tag is a label pointing at a manifest. Pushing a new image with the same tag moves the pointer, and the old image becomes unreferenced.
This means myapp:1.4.2 today and the same string next week may be entirely different content. The version number implies immutability and provides none.
latest is the extreme case and the best understood. The subtler problem is semantic version tags, which people assume are stable because the convention suggests they should be. Nothing in the registry enforces that assumption.
The Failures This Produces
Untraceable deployments. A pod running myapp:1.4.2 gives no way to determine which build it actually contains. During an incident, correlating running code to a commit becomes guesswork.
Inconsistent replicas. Pods scheduled at different times pull whatever the tag pointed at then. With imagePullPolicy: IfNotPresent, some nodes have a cached older image while others pulled a newer one, so replicas of the same deployment run different code.
Broken rollback. Rolling back to a previous tag retrieves whatever that tag points at now, which may not be what was running before.
Supply chain exposure. Anyone who can push to the registry can silently replace the content of a deployed tag without any change to your manifests or any deployment event.
Using Digests Instead
A digest is a content hash of the manifest, referenced as myapp@sha256:abc123.... It identifies exactly one immutable image. Pushing new content produces a different digest, so the reference cannot be repointed.
| Reference style | Reproducible | Traceable | Practical to write |
|---|---|---|---|
latest |
No | No | Yes |
1.4.2 |
No | Partly | Yes |
1.4.2 with immutable tags enforced |
Yes | Yes | Yes |
@sha256:... |
Yes | Yes | Needs automation |
Digests are unreadable by hand, which is why the practical arrangement uses both: tag the image for humans and deploy by digest resolved at build time. The CI pipeline knows the digest it just built and writes it into the manifest, so the deployment references exactly what the pipeline produced.
Registry-level tag immutability is the complementary control. Configuring the registry to reject overwriting an existing tag makes tags trustworthy, which preserves readability without sacrificing reproducibility. Enabling it costs nothing and prevents the entire class of problem.
Related Configuration
Set imagePullPolicy: Always if deploying by mutable tag, which forces a registry check and at least makes replicas consistent — at the cost of a registry dependency on every pod start. Deploying by digest makes the policy irrelevant, since the digest cannot have changed.
Sign images and verify signatures at admission. A digest guarantees the content is unchanged; a signature guarantees it came from your pipeline. Together they close the path where an attacker with registry access injects an image.
The Bottom Line
Enable tag immutability in your registry, tag images for human readability, and have CI resolve and deploy by digest. That combination gives reproducible deployments, honest traceability from running pod to commit, and a rollback that returns to what was actually running.



