✦ For everyone, free.

Practical knowledge for real and everyday life

Home

17.3.2.2 Production Tag Practice

A focused guide to Production Tag Practice, connecting core concepts with practical Docker and container operations.

Production tag practice covers the actual naming scheme and registry-level enforcement around how production image tags are structured and protected, distinct from the broader decision to prefer digests over tags at deployment time, focused on establishing a consistent, meaningful tagging convention and preventing that convention from being violated through accidental tag reuse.

Adopting a consistent semantic versioning scheme

A predictable, semantic versioning scheme, major, minor, and patch components reflecting the actual nature of the change, gives every tag immediate, useful meaning about what kind of change it represents relative to the previous release:

docker build -t my-api:1.4.2 .
docker build -t my-api:build-47291 .

The first tag immediately conveys meaningful information through its structure alone, a patch-level change relative to 1.4.x; the second conveys nothing beyond an opaque, incrementing build number, requiring a separate lookup to understand what actually changed or how significant the change might be.

Mapping git tags directly to image tags

Establishing a direct, one-to-one mapping between a git tag and the corresponding image tag makes it trivial to move between source control and the published artifact in either direction, without needing a separate system of record to track the correspondence:

git tag v1.4.2
git push origin v1.4.2
docker build -t my-api:1.4.2 .
docker push registry.example.com/my-api:1.4.2
git checkout v1.4.2

This direct mapping means anyone investigating a specific deployed version can immediately check out the exact corresponding source commit, and vice versa, anyone looking at a specific commit or git tag can immediately identify the corresponding image tag, without any ambiguity or additional lookup required.

Enforcing tag immutability at the registry level

Many container registries support configuring specific tags or entire repositories as immutable, rejecting any attempt to push to an already-existing tag, which converts the convention of "never reuse a production tag" from a matter of discipline into an actually enforced, registry-level guarantee:

aws ecr put-image-tag-mutability --repository-name my-api --image-tag-mutability IMMUTABLE
docker push registry.example.com/my-api:1.4.2
denied: tag 1.4.2 already exists and is immutable

This kind of enforced immutability removes the possibility of an accidental retag, whether from a mistaken rebuild reusing an already-used version number or, in a worse scenario, a deliberate, unauthorized attempt to substitute different content under an already-trusted tag.

Conventions for pre-release and release candidate tags

For versions not yet considered a final, stable release, an explicit, conventional suffix distinguishes pre-release builds clearly from production-ready ones, preventing ambiguity about a given tag's actual readiness:

docker build -t my-api:1.5.0-rc.1 .
docker build -t my-api:1.5.0-beta.2 .
docker build -t my-api:1.5.0 .

Following a widely recognized convention, such as semantic versioning's pre-release suffix syntax, rather than an ad hoc, project-specific naming scheme, makes the distinction immediately understandable to anyone familiar with the broader convention, not just people already familiar with this specific project's own internal naming habits.

Tag promotion versus rebuilding for each stage

A release candidate that passes its validation should be promoted to its final, stable tag by retagging the exact, already-validated digest, never by rebuilding from source under the final tag name, since rebuilding risks producing genuinely different content than what was actually validated under the release candidate tag:

docker pull registry.example.com/my-api:1.5.0-rc.1
docker tag registry.example.com/my-api:1.5.0-rc.1 registry.example.com/my-api:1.5.0
docker push registry.example.com/my-api:1.5.0

This retagging approach guarantees the final, stable tag points at the exact, byte-identical content that was actually tested under the release candidate tag, rather than a fresh, potentially different rebuild that merely shares the same source code at the time it was triggered.

Documenting the tagging scheme for the entire team

A brief, explicit document describing the project's actual tagging convention, what each component of the version number means, how pre-release tags are structured, when and how promotion happens, removes ambiguity for anyone releasing a new version, particularly relevant for a project with multiple people authorized to cut releases who might otherwise each develop slightly different habits:

# RELEASING.md
Versions follow semver: MAJOR.MINOR.PATCH
Release candidates: MAJOR.MINOR.PATCH-rc.N
Promotion: retag the validated rc digest to the final version, never rebuild.

Auditing tags for convention compliance

Periodically reviewing existing tags against the documented convention catches drift, a tag that does not follow the established naming scheme, or evidence that the no-rebuild-for-promotion rule was not actually followed, before that drift becomes a larger, harder-to-untangle inconsistency across the project's release history:

docker images registry.example.com/my-api --format "{{.Tag}}"

Reviewing this list against the documented convention surfaces any tag that does not conform, which is worth investigating directly rather than assuming every past release followed the convention correctly without verification.

Common mistakes

  • Using opaque, non-meaningful tags like raw build numbers instead of a consistent semantic versioning scheme that conveys useful information through its own structure.
  • Not maintaining a direct, one-to-one mapping between git tags and image tags, requiring a separate, manually maintained system of record to track the correspondence.
  • Relying entirely on team discipline to never reuse a production tag, rather than enforcing immutability directly at the registry level.
  • Rebuilding from source under a final, stable tag name rather than promoting the exact, already-validated digest from its release candidate tag.
  • Not documenting the project's actual tagging convention, leaving multiple people authorized to cut releases to each develop slightly different, inconsistent habits over time.

Production tag practice establishes a consistent, meaningful naming scheme directly mapped to source control, enforced through registry-level immutability rather than discipline alone, with pre-release tags following a recognizable convention and promotion handled through retagging an already-validated digest rather than a fresh rebuild, all of which together keep a project's release history both meaningful and verifiably accurate.