Docker Image Names for Dummies
Table of Contents
One thing I’ve noticed in people starting to learn about Docker,
is that there is a lot of confusion about image names. What’s the difference
I’m going to try and break it down.
The name of a Docker image is made of a number of pieces. The confusing part is
that nearly every piece is optional and can mixed and matched, along
with non-obvious defaults. I’m going to work left to right in the image name, with
the example of the base
The first piece of any Docker image name is the registry. The registry is just the server the image comes from (or at least tagged to). A whole discussion on Docker registries is here.
By default, the registry
docker.io is used, so the following two images are the same:
Fun fact, for extra confusion, the registry
docker.io is also available under
many different names including:
Another point about the registry, is this it is just a web server so if you are running your own, IP addresses and port numbers can also be used:
After the registry, followed by a
/, comes the user.
The user is the person or organization that
owns the image. Like the registry, this is optional, and defaults to
so the following two images are the same:
This is also why in the web UI for Docker Hub, library images have a different URL than non-library images:
HOWEVER, this is not always the case, and actually varies by
server implementation. The default Docker Hub registry does this, but not
all registries do. For example, the
Quay registry software allows you to enable this
feature, but on the other hand as far as I’m aware,
Azure Container registry
does not do this and will let you name images with or without user names
and does not do any
After the user, followed again by a
/, is now the image repository.
This is more or less the name of the image itself.
In our example, the repository is
python. This is
the only piece of the image name that is actually required.
Finally, is the tag of the image, which follows the repository name with a
This is basically the version specifier of the image.
The tag is optional, and defaults to
latest tag has no
special properties, nor does it even have to be defined,
it’s just by convention the most recent version of the image.
Once again in our example, the following two images are the same:
Tags are user-defined and can be almost anything. In our
python example image, this includes things like
A confusing part about tags is that unlike most package registries (npm, PyPi, etc.),
tags can be overwritten or deleted at any time. This how
latest tags are usually used,
by always assigning it to the last image pushed. Additionally, an image can have
multiple tags. Once again in our example, the following two images are the same
(at time of writing):
To help users select specific versions of images, large projects often tag things in multiple ways, depending on how specific you want to be. For example:
python:latest: The latest version of Python
python:3: The latest version of Python 3
python:3.10: The latest version of Python 3.10
python:3.10.0: Python 3.10.0 exactly. Maybe receive security fixes to the image
Okay, there is actually one last piece of the image name, which is the digest.
These are mutually exclusive to tags are not commonly used.
Instead of separating the repository and tag with a
:, you separate a repository and
digest with a
@. These reference a specific version of the image
based on a hash of the content of the image. Unlike user-defined tags,
these can not be changed. These take the form of (nearly always)
Once again, these two images are the same (at time of writing):
Today we’ve learned about Docker image names are constructed, and how all of the following (at time of writing) are the exact same image:
Personally, I like to be explicit and specific as reasonably possible. In my Dockerfiles, I would usually do something like: