Learning paths / Containers / Registries

Registries, repositories and tags

Reading · 5 min · Module 5, lesson 1 of 427 min left in this module

Module 5 · RegistriesLesson 1 of 4

Goal: Read and write an image's full name, registry/repository:tag, and know what Docker fills in when parts are left out.

Key idea

An image built on your laptop exists only on your laptop. To run it anywhere else, you push it to a registry, and its full name says exactly where it lives: registry / repository : tag.

   quay.io / computesphere/learn-hello-web : 1.0.0
   ───┬───   ──────────────┬─────────────   ──┬──
   registry            repository              tag
   (the server)   (owner / image name)    (which version)

The three parts

Registry: the server that stores images. Docker Hub (docker.io), GitHub Container Registry (ghcr.io) and Quay (quay.io) are public ones. Cloud providers run their own, such as Azure Container Registry and Amazon ECR.

Repository: one image's home in that registry, usually owner and name: computesphere/learn-hello-web. It holds every version of that image.

Tag: a label for one version in the repository: 1.0.0, 2026-09-29, latest. The same image can carry several tags.

What Docker fills in

Short names are shorthand. Docker completes them the same way every time:

you type                        Docker reads
postgres:16                  →  docker.io/library/postgres:16
octocat/compose-web:1.0.0    →  docker.io/octocat/compose-web:1.0.0
ghcr.io/octocat/compose-web  →  ghcr.io/octocat/compose-web:latest

No registry means Docker Hub. No owner on Docker Hub means library, where the official images live. No tag means latest.

You can see this when you build: docker build -t compose-web:1.0.0 . ends with naming to docker.io/library/compose-web:1.0.0.

Naming for a push

The name decides where docker push sends the image, so it has to point at a repository you own:

  • Docker Hub: <your-username>/compose-web:1.0.0
  • GHCR: ghcr.io/<your-username>/compose-web:1.0.0

Names are lowercase, even when your username isn't. docker tag adds a second name to an image you've already built; both names show the same image ID in docker image ls, because nothing is copied.

Tags move, so pick them on purpose

A tag is a pointer, and whoever pushes can move it to a different image. latest moves on every push, so two servers pulling latest an hour apart can get different code.

Tag each release with its own version, like 1.0.0, and deploy that tag. For an exact, unchangeable reference there's the image's digest, from lesson 3.2.2; ComputeSphere deploys by tag today, so a version tag you never reuse is how you pin.

Check yourself

What's the full name of the image python:3.12-slim?
Your teammate pushed a fix to my-app:latest. Your server pulled my-app:latest yesterday. What's it running?