Ask ten .NET developers how they name their Docker images and you’ll probably get as many answers. Each approach has its pros and cons, so it’s good to know what they are to make the decision that is right for your project.
What’s In A Name
A Docker image’s name can be broken up into parts, separated by a colon. The first part is called the repository and the second part is called the tag. For example, aspnet:3.1-buster-slim’s repository is
aspnet and its tag is
The repository name is mandatory; it’s how you identify the image in Docker. The repository should be something descriptive that identifies what is contained in the image. I’ll usually combine the name of the component with an abbreviation that tells me what it is. For example, I’d name an API for placing orders the
orders-api and an application for placing those orders from the web as the
orders-app. Similarly, I’d use a name like
orders-wrk to represent a worker performing some asynchronous background tasks.
A repository name can contain slashes to structure your images. For example, I can create a structure to more easily identify what an image does, for example
roversoftware/app/frontend. This type of repository name makes it easier to pick out which images are yours and which are not.
An image can have zero, one, or many tags. The tag lets you be more specific about versions, operating systems, and any other relevant detail to how the image is built. One of ASP.NET Core’s tags is
3.1-buster-slim, indicating that the image contains ASP.NET Core 3.1, based on the trimmed down (“slim”) variant of the Buster release version of Debian.
There are many recommendations on the web about how to name your tags. Generally, they include one or many of the following pieces of information:
- Some type of Semantic Versioning. Examples:
- The commit hash from which the image is based. Examples:
- The build identifier that created the image. Examples:
- The date and time the image was built. Example:
- Any other relevant details to identify the image. Example:
What you include in a tag depends on the type of image you’re building. Tags can be broken down into two categories: Stable Tags and Unique Tags.
A Stable Tag is usually based on semantic versioning and is mostly for base and parent images that aren’t run directly in a container, but are instead the parent for another image. A stable image tag indicates that the image won’t be receiving code updates, but could be updated for things like security patches. For example, I might have a base image called
roversoftware/mybaseimage with a
v1.0 tag. The day that image needs an underlying framework fix, I could apply the fix, re-use the
v1 tag and create a
v1.1 tag. This way, my deployed images that are bound to the
v1 tag receive the update automatically the next time the container is restarted. An image that shouldn’t be rolled forward automatically could instead use the
v1.0 tag, which would require me to explicitly change the Dockerfile to use the
A Unique Tag is used for images that you create with the intent to run in a container. The
orders-app would be examples of this type of image. The unique tag could be composed of any of the above naming conventions, but avoid using the semver option. Semantic versioning isn’t well suited to deployed images because they make it hard to trace back where and when the image was built.
The Choice Is Up To You
Ultimately, you can use whatever scheme you want to name and tag your images. Every project is unique and will have its own requirements. The only real rule of thumb is to use stable tags for base and parent images, and unique tags for deployed images. It’s always possible to change your naming scheme later without too much of a hassle.
Finally, if you’re looking for more detailed information about which tags are best and why, I highly recommend Steve Lasker’s post on the subject.