DEV Community

ahmad bayhaqi
ahmad bayhaqi

Posted on

What Docker Image Tag Should You Actually Use?

I’ve been working with containerized applications for a while, and one thing that always confused me in the beginning was Docker image tagging.
Nobody explained it properly.

I just followed whatever the team did, pushed images, and hoped things worked.

But over time.. especially when handling multi-tenant apps, shared registries, and too many deployments. I started to see how bad tagging decisions can break everything.

So here’s my experience and what I learned the hard way.

The moment I realized “latest” is a trap

When I first started using Docker, I thought:

“Ah, just push it with latest. Simple.”

Until one day, a tenant’s production environment suddenly rolled back to a previous version.
Why?

Because someone else on the team pushed a new image with the same latest tag. The registry replaced it silently. The cluster pulled it automatically. Chaos.

That’s the moment I understood:

  • latest is not a version
  • latest is not safe
  • latest will eventually hurt you

But I didn’t stop there. I kept experimenting with different tagging styles.

The Semantic Versioning Phase

After the latest catastrophe, we switched to semantic versioning:

v1.2.3
v1.2.4
v1.3.0
Enter fullscreen mode Exit fullscreen mode

And honestly... it felt clean.

Every release had a meaning.

We knew which version fixed what.

Rollback was easy — just redeploy the previous version.

But then reality hit:

  • My team was not disciplined enough.
  • People forgot to update the version.
  • Someone tagged two different builds with the same version.
  • And sometimes we just wanted to test something quickly, but bumping semantic version felt “too heavy”.

Semantic versioning worked well for production, but not so much for day-to-day development.

Branch-Based Tagging: Easy but Dangerous

Then we tried a simpler approach:

dev
staging
production
Enter fullscreen mode Exit fullscreen mode

It felt nice.

Our CI/CD pipeline was clean.

Each environment had its own tag.

But later, when our application grew into a multi-tenant product, things got messy.

Imagine this scenario:

  • Tenant A and Tenant B both use development tag
  • You push a new feature for Tenant A
  • Cluster for Tenant B also pulls the new development image (because it’s the same tag)
  • Tenant B breaks

This happened to us more times than I’m proud of.
And again, older images became “untagged” when new ones reused the same tag.

No trace.
git-revert rollback.
I knew we needed something safer.

Finally: Branch + Commit Hash

This was the game changer.
Instead of just development, we started tagging like this:

development-a1b2c3d
development-f39e2a1
production-c41e162
Enter fullscreen mode Exit fullscreen mode

Just 7 characters of the commit hash, unique, simple, and enough to avoid collisions.

Suddenly:

  • Every image had a unique identity
  • Rollbacks became extremely easy
  • Multi-tenant setup was safe
  • Nothing accidentally overwrote something else

The only downside?!

Registry will populate a lot of different tags

Our container registry filled up fast.
We had to implement retention policies.

But honestly, compared to breaking tenants?

I will happily pay for storage.
This tagging style solved everything semantic versioning and branch tagging couldn’t.

So what do I actually recommend?

From my own experience,

For development:
Use branch + commit hash

Example:

development-7f92c3a
Enter fullscreen mode Exit fullscreen mode

It keeps things safe, traceable, and rollback-friendly. cover frequently changes on development.

Tips
keep latest image (e.g. development-latest). you may push alternative tag on single commit.
dont worry it doesn't take your storage, just tag. it will help you to trace which latest tag quickly

For production:
Use semantic versioning

Example:

v1.4.0
Enter fullscreen mode Exit fullscreen mode

Clean, stable, professional.

For personal or hobby projects:
Just use latest or dev.
No need to over-engineer.

Top comments (0)