Docker Tag Re-Assignment and the „latest“ Tag
Introduction
The Docker
latest tag can be a bit of mystery.
The
confusion is mostly based on the legitimate assumption that an image tagged “latest” is the last and therefore newest image added to a given repository.
This
assumption, legitimate or not, is definitely wrong. The tag “lastest” is just a
token like “0.1.1” or “iojdfh”.
The only thing that makes "latest" special is that Docker assumes it as a default value for its “docker commit” or “docker tag” commands in case you do not specify a tag explicitely.
The following links cover this in great detail.
Marc
Campbell: The misunderstood Docker tag: latest
Adrian
Mouat: Docker: The latest Confusion
Nothing
left to add to these.
What I want
to shed some light on here, is:
- how Docker treats tags as pointers to images
- how Docker distinguishes between creating and re-assigning tags
As always, if you know all that then don’t waste your time and stop reading now.
If you are not so sure, keep going. I admit that some details of tagging have been a surprise to me.
Setup
Let’s start
out with creating a setup just rich enough to see the mechanics.
Creating a
repository containing two versioned images will just do it.
Please note upfront:
- I’m on Windows 10, running my docker in Vagrant powered CentOS 7 VirtualBox
- I’m working locally, not pushing to or pulling from Docker Hub (except when running the base image)
- I’m not using a dockerfile but create my images by committing containers
Now let’s
create the images:
# # Run Container based on base image „centos“: $ docker run -it centos /bin/bash #
This will
start an interactive container running a bash shell and You will find yourself
within this shell.
Create a file “/test.sh”, e.g. using vi, and enter this content:
# #!/usr/bin/env bash echo "Hello, I am version 01"
Now exit
the container and commit it to a version 1 image:
# $ docker commit -a "volker.koster@mt-ag.com" -m "Added /test.sh" \ -c 'CMD ["/bin/bash", "/test.sh"]' 333ba1982dbe vkoster/versionen:v01 #
Things to
note here:
- 333ba1982dbe is the container’s id
- The --change option makes this container an executable that just runs the /test.sh file
- vkoster/versionen is the name of the repository for our images
- v01 is our version tag
Had we not
specified the version tag, docker would have assigned “latest” as a default
tag. Told differently, docker did not assign the “latest” tag because we
specified a tag explicitely.
Now list the images and run a container to see if it works:
# $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE vkoster/versionen v01 51e388437466 26 seconds ago 196.7 MB $ docker run vkoster/versionen:v01 Hello, I am version 01 #
(Omitting the "v01" tag now, would have caused an error, because Docker would then assume "lates", which is not present)
Image works. Let’t tag it as “latest”:
Image works. Let’t tag it as “latest”:
# $ docker tag vkoster/versionen:v01 vkoster/versionen:latest $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE vkoster/versionen latest 51e388437466 10 minutes ago 196.7 MB vkoster/versionen v01 51e388437466 10 minutes ago 196.7 MB #
We now have
one repository containing one image referenced by two tags.
Now let's create
version 2 of this image.
# $ docker run -it vkoster/versionen /bin/bash #
(Now it is ok to omit the tag: Docker assumes "latest", which is now present)
Within the running container, edit the /test.sh file like so:
# #!/usr/bin/env bash echo "Hello, I am version 02" #
Save the
file, exit the container and again commit it to an image:
# $ docker commit -a "volker.koster@mt-ag.com" -m "Changed /test.sh" \ -c 'CMD ["/bin/bash", "/test.sh"]' 5f1f1063fd2a vkoster/versionen:v02 #
List the
images and run the new version, just to be sure.
# $ docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE vkoster/versionen v02 435bb586c058 5 minutes ago 196.7 MB vkoster/versionen latest 51e388437466 57 minutes ago 196.7 MB vkoster/versionen v01 51e388437466 57 minutes ago 196.7 MB # …and run the image: $ docker run vkoster/versionen:v02 Hello, I am version 02 #
We still have
one repository, now containing two images.
As was expected and covered in the links above, the “latest” tag did not move but still references the first image.
Now we can play around with the tags a bit.
As was expected and covered in the links above, the “latest” tag did not move but still references the first image.
Now we can play around with the tags a bit.
Questions
Question:
what will happen, if we try to tag the new image with the “latest” tag?
Obviously there cannot be two “latest” tags in one repo.
Obviously there cannot be two “latest” tags in one repo.
Tag the new image with “latest” and display the results:
# $ docker tag vkoster/versionen:v02 vkoster/versionen:latest $ docker images –a REPOSITORY TAG IMAGE ID CREATED SIZE vkoster/versionen latest 435bb586c058 9 minutes ago 196.7 MB vkoster/versionen v02 435bb586c058 9 minutes ago 196.7 MB vkoster/versionen v01 51e388437466 About an hour ago 196.7 MB #
As it
worked, this is what happened:
- we tried assign the “latest” tag
- Docker recognizes that the repository already contains the tag “latest”
- therefore, the tag is not created but simply re-assigned to point to the new image
- there is only one pointer left, “v01”, to point to the first image
Question: Are all tags treated like this or is the “latest” tag special?
This works for all tags. Again, the tag “latest” is in no way special.
You can try this yourself by re-tagging “v01” or “v02”.
Question:
What happens when we remove the last tag from an image?
# $ docker tag vkoster/versionen:latest vkoster/versionen:v01 $ docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE vkoster/versionen latest 435bb586c058 57 minutes ago 196.7 MB vkoster/versionen v01 435bb586c058 57 minutes ago 196.7 MB vkoster/versionen v02 435bb586c058 57 minutes ago 196.7 MB <none> <none> 51e388437466 About an hour ago 196.7 MB #
Docker re-assigned the pointer with no problem at all, leaving our fist image “naked”.
This image can no longer be referenced via the repository.
This image can no longer be referenced via the repository.
Takeway
The results can be summed up like this:
- tags are just pointers to images
- when tagging, docker checks, if the respective tag is already present within the repository
- if the tag is not present, it is created, pointing to the respective image
- if the tag is present, it is simply re-assigned from one image to another
- this works for all tags; there is no special treatment for “latest” whatsoever
No comments:
Post a Comment