Search code examples
dockerversioning

Properly Versioning Docker Images


Following on the 4-year-old question Docker image versioning and lifecycle management, because IMHO it did not address versioning Docker Images properly:

I don't find this answer to be adequate, as there can be successive versions of the same tag. We need a way to be able to lock down dependencies onto a particular version of a tag.

and also,

the answer is to not use latest.

The "solution" I found on the web is confusing too. E.g.,

  • Here it hinted not use latest, and the "solution" hinted to be tagging twice. I emphasize on "hinted" because there is no solid recommendation (to me).
  • And here it even shows that we need to do docker push twice on the same image.

So, how to properly versioning Docker Images (both locally and when pushing/publishing to docker hub)?

AMEND:

So far there are two answers. Thanks for that.

  • Both use git's short version ID.
  • And both miss the pushing/publishing part from the answer.

As I do need to push/publish my docker image to Docker repository, and from here it hinted that not using latest will give you trouble when pulling the latest, if you go with specific ID tagging. Moreover, using git's short version ID might be a good solution for internal use, but when publishing docker image for public consumption, it then might not be the best solution.


Solution

  • Docker gives no semantic meaning at all to tag values. A tag can be any string value at all, and tags can be reused. The only special tag value is that if you just say imagename in a docker pull or docker run command, it is automatically interpreted as imagename:latest.

    Mechanically, you can give the same image multiple tags, but you need to docker push all of them. The expensive part of the push is the layer content and so this will mostly just push the fact of the alternate tag on an existing image. Similarly, pulling an image tag, if it's a duplicate of an image you already have, is all but free, but there's no easy way to find out all of the tags for a given image.

    I would recommend:

    1. Give every build a unique identifier, something like a source control commit ID or a timestamp.
    2. If and when you do official releases, also tag builds of that release with the release number. (More generally, if the current source control commit is tagged, tag the Docker image with the source control tag.)
    3. If it's useful for your development workflow, also tag builds that are the tips of branches with their branch name.
    4. Given its prominence it's probably useful to tag something as latest (maybe the most recent release).
    5. Avoid using latest and other tags that you expect to change when referring to built images (in docker run commands, Dockerfile FROM lines, Kubernetes pod specs, ...).

    This combination of things could mean the same image is tagged imagename:g1234567, :1.2.3, :master, and :latest, and your CI system would need to do four docker pushes. You would probably expect the first two images to be fairly constant, but the latter two to change routinely. You could then run something like imagename:1.2.3 with some confidence.

    (The one special case that comes to mind is a software package that changes rarely and so might need to be rebuilt if there are upstream fixes or security updates. It seems typical to reuse the same tag for this: for instance, ubuntu:18.04 gets updated every week or two.)