Quick Links

Docker images use registries for version control, such as the Docker Hub that hosts public images for anyone to download and run. However, before uploading an image to the Hub or any registry, you must give it the proper tags.

Container vs. Image

It's important to understand the difference between containers and images before talking about tags, as they're often used fairly interchangeably and that can lead to some confusion.

A Docker image is what you get from running

        docker build
    

 with your Dockerfile. It's made up of multiple layers to optimize disk and memory usage. An image is a read-only.

A Docker container is an instance of an image that the processes actually run in. It's a read/write file system, so essentially, an image is a template that you use to create multiple containers from. It contains the base code and everything the app needs to get started. The containers get initialized with the image when created, then it can modify the file system as they please.

Images are what you push to the container registry. Then, on your servers, you can reference the image in the registry to download the container.

Tags Track Versions of Built Images

Whenever you run a

        docker build
    

, you create a new image with a unique ID, like "38054d5e8a27."

Tags are simply labels that provide a better way to manage version control and releases. They're like labels that you can assign to any completed build. Rather than referencing the build ID, you can tag an image with a label in the major.minor.patch format and easily be able to tell which image is which, or whatever format your organization prefers.

Tagging is pretty easy. You can use

        docker tag
    

 to do it after the fact, but it's much easier to do it when you build using the

        -t
    

 flag:

 docker build -t repository/image:tag .

This builds the image from the Dockerfile and tags it with the tag you specified. The tag is the [:TAG] part, after the semicolon, even though Docker will say "Successfully tagged repository/image:tag." The repository/image part is just the name of the image, and if you're planning on pushing to a repository, you must tag it in the repository/image:tag format.

For Docker Hub, the repository name is just your username, so the command would look something like:

 docker build -t anthonyheddings/nginx:tag .

If you don't specify a specific tag, Docker automatically tags it as "latest."

Another common practice is to tag the image with the git commit ID, thereby linking the version control with the built images. You can automate this pretty easily with git rev-parse:

docker build -t vicerust/core:$(git rev-parse --verify HEAD) .

Once an image is tagged, you can push it to the registry with docker push, passing in the repository/image name:

docker push repository/image

From there, you're able to access it in docker run as normal. If you don't specify a tag, docker run automatically uses latest.

Latest Doesn't Always Mean "Latest"

The "Latest" tag is a bit confusing. Despite how the name sounds, it doesn't always point to the latest release. It's simply a special tag that gets assigned automatically whenever you don't specify a tag. This has the effect of avoiding tags altogether and just pushing a "latest" version.

You can use the latest tag either by just not specifying a specific tag:

 docker build -t repository/image .

Or by manually tagging an image as latest:

 docker build -t repository/image:latest .

which works well if you're only using the latest tag. But if you want to also use version ID tags, you'll need to double-tag your images every time, which can lead to "latest" not always meaning the last built image. It's good practice to avoid using latest alongside other tags to prevent this confusion. Just version your tags, every time, either with manual patch numbers or with git commit IDs.