^ Thanks DALL·E for the “knitted docker whale”
TLDR;
- Avoid using the
latesttag for your Docker images: This will lead to compatibility issues; always version pin using Semantic Versioning - Use
RCDocker tags for branches which aren’tmain - Use a task in your pipeline to check if the target Docker tag already exists in your Docker Container Registry
- Use a clean up task (repo: desholmes/acr-tag-deleter) in your CI/CD pipeline, or Docker Registry policies to keep your Docker Registry tidy
Clone the Open Source desholmes/dholmes.co.uk-blog-frontend-code-quality-example repo and follow the post below…
Introduction
Knowing which strategy to use for generating Docker tags can be challenging. However, if you keep it closely aligned to a trunk-based git branching strategy you’ll save yourself a world of pain and you’ll have deployable, immutable infrastructure to “run anywhere” throughout your development cycle.

The above shows a simple, trunk-based git branching strategy. It branches from main at version 1.0.0 and merges back into main as 1.1.0 after 4 commits.
Your repo will need a way of tracking the version, for Node.js you can use the package.json version, and for Python and Java you can use a version.properties file.
Let’s assume you have a CI/CD pipeline in place to run all of your quality control checks (lint, unit tests etc). Now, as well as running your tests, you’re also going to be building and pushing a Docker image to your Container Registry for each push to your remote.
Within the pipeline we’ll configure a Release Candidate (RC) build, using the target Docker tag version combined with the build number (ie: 1.1.0-rc.1 for the first build in your pipeline).
At the point of merging your git branch back into main you will build and push a Docker tag using 1.1.0, and run a clean up step to remove the associated RC tags from your Docker Container Registry.
Walking through the process
Clone the Open Source desholmes/dholmes.co.uk-blog-frontend-code-quality-example repo and follow along with the steps below.

- Git branch
feature/add-more-greetingsis created locally frommainand the version in package.json is bumped to1.1.0 - We make the first commit and push to the remote
- The CI/CD pipeline builds a docker image
1.1.0-rc.10(assuming there have been 9 previous pipeline executions to get version1.0.0merged intomain) - 3 more commits and pushes are made to the remote, these result in
1.1.0-rc.11,1.1.0-rc.12,1.1.0-rc.13being built and pushed to the Docker Container Registry - A pull request is raised and the branch is merged into
main - A CI/CD pipeline build is triggered resulting in
1.1.0being built and pushed to the Docker Container Registry and a final task is executed in the CI/CD pipeline to removeRCbuilds1.1.0-rc.10-1.1.0-rc.13from the Docker Container Registry
Dealing with clashes
What if another developer is targeting my version? And… How can I make sure my tag isn’t already in my Docker Container Registry and will get over written?
This is the final piece of solution. Within your CI/CD pipeline your first task to will need to check if the Docker tag your are targeting (1.1.0 in the walk through above) already exists in your Docker Container Registry.
If it does your pipeline should fail and output a “The tag 1.1.0 already exists in the Container Registry, bump the version and try again.” message.
This will ensure you don’t Docker push over existing tags.
Popular related posts for Azure, Azure DevOps and CI/CD:
