Using tags
Tags are descriptors to label different versions of the same image. There's an image, alpine:3.9, and another, alpine:3.8. There are also official images of Python for different interpreters (3.6, 3.7, 2.7, and so on), but other than versions, the interpreters may refer to ways the image is created.
For example, these images have the same effect. The first one is a full image containing a Python 3.7 interpreter:
$ docker run -it python:3.7
Python 3.7.3 (default, May 8 2019, 05:28:42)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
The second one also has a Python 3.7 interpreter. Note the slim change in the name:
$ docker run -it python:3.7-slim
Python 3.7.3 (default, May 8 2019, 05:31:59)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
However, the sizes of the images are quite different:
$ docker images | grep python
python 3.7-slim ca7f9e245002 4 weeks ago 143MB
python 3.7 a4cc999cf2aa 4 weeks ago 929MB
Any build uses the latest tag automatically if another tag is not specified.
A single image can be tagged multiple times, with different tags. For example, the latest tag can also be version v1.5:
$ docker tag thoughts-backend:latest thoughts-backend:v1.5
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thoughts-backend latest c7a8499623e7 5 min ago 144MB
thoughts-backend v1.5 c7a8499623e7 5 min ago 144MB
Note how image id is the same. Using tags allows you to label specific images, so we know they are ready to deploy or give them some kind of significance.