In the previous post, we talked about how Chainguard constructs its tags when the image contains versioned multiple components.
Let's ignore the practical UX issues of such a long tag, and the combinatorial explosion of tags you'd need to wade through to find the image you want – we can invent search/browsing UIs for finding the tag, and if the tag gets too long (they're capped at 128 characters) we can invent a hairbrained scheme to encode and compress that information so it fits in the tag. If you still think this is a good idea, you're not totally wrong: you've basically invented image digests, which already exist.
The image digest is a 64-character hex-encoded SHA-256 hash of the contents of the image. It's not just based on the packages contained in the image, but the contents of every file in the image, and it covers metadata about the image too – the environment variables, entrypoint, user, creation timestamp, everything. Changing any of these bits of information would result in a new image digest.
When pulling an image by digest, container runtimes check that the contents they pulled match the given digest, so you don't even have to take our word for it, the digest is the canonical ID of an image by its contents. And it's shorter than that 128-character tag scheme we almost invented earlier!
Comparison with Git Tags
Container images don't have the concept of branches. Instead, the ecosystem seems to have broadly adopted a convention that some image tags should be expected to move (like Git branches), and some should be expected not to move (like Git tags).
And in any case, as demonstrated above, there's a lot more to that single version tag than meets the eye, especially if you want to deliver image updates that fix vulnerabilities in all of the image's components. Which we very much do!
Image Tags are Mutable, Even Immutable Tags
Some smart folks, trying to save themselves from the widespread convention that some tags should be expected to move and others shouldn't, decided to make their registry enforce immutable tags. This was a well-meaning, but incomplete, solution.
A well-meaning SRE might disable tag mutability during a late-night outage to get production back up and running, and simply forget to re-enable it. The only thing worse than mutability is ambiguity about mutability.
Immutable tags are like having a plastic flip-up cover on a Big Red Button. Sure, it's good to have a safeguard against accidental changes, but when it's really important, you want something more than a piece of plastic involved.
If immutability is really what you're after, accept no substitutes – you want digests. I know, I know, they're long inscrutable hex-encoded gibberish, but they have one job and they do it well: they succinctly and provably describe all of the contents of an image, and they'll never change.
In the third and final installment of Chainguard’s Image Tagging Philosophy, we’ll dive into how Chainguard deploys by digest, why sometimes digests aren’t enough, and what you can do about it.