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:
- Give every build a unique identifier, something like a source control commit ID or a timestamp.
- 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.)
- If it’s useful for your development workflow, also tag builds that are the tips of branches with their branch name.
- Given its prominence it’s probably useful to tag something as
latest(maybe the most recent release). - Avoid using
latestand other tags that you expect to change when referring to built images (indocker runcommands, DockerfileFROMlines, 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.)