1.1 · Images: tags, layers and Docker Hub

Level 1 · Containers: images, volumes, networks

1.1Images: tags, layers and Docker Hub

Goal: choose the right image with the right tag and understand its layers.
Estimated time: 12 min · self-paced reading · If you only have 5 min: read “The essentials in 30s” + the diagram.

The essentials in 30 seconds

  • The tag is the version: postgres:16 pins the major, postgres:16.4 the minor, postgres:latest follows the latest (so it changes without warning) — in production, always pin a precise tag and write it down.
  • Stacked and shared layers: an image = a stack of read-only layers, cached and shared between images — ten images on the same base download the base only once.
  • Choosing without going wrong: official images (verified maintainer), supported tags read in the docs, update date and architecture (amd64/arm64) checked — an image abandoned for two years is a security risk.

Running mini-case — Idir, junior DevOps in Algiers

Idir, junior DevOps in Algiers, has to containerize the database of a small internal application. Instead of typing « postgres » and taking the first suggestion, he opens the official page on Docker Hub, compares the tags and settles on postgres:16.4: pinned version, up to date, available in amd64 and arm64. He notes this choice in a versions.txt file shared with his team. Six months later, when a colleague relaunches the environment on another machine, he gets exactly the same behavior — because the tag has not moved.

This same case returns in the lesson, the diagram, the script and the 48h challenge — and continues in 1.2, 1.3, 1.4 and 1.5.

1. The tag is the version

After the « : », the tag designates the variant of the image: postgres:16 pins the major version, postgres:16.4 the minor, postgres:latest follows the latest available — so it changes without warning. In development, following latest is acceptable; in production, always pin a precise tag and write it down (Idir writes it in versions.txt).

The rule in one sentence: pin in production, follow while exploring. A reproducible deployment starts with a tag that does not move.

2. Stacked and shared layers

An image is a stack of read-only layers: each build instruction adds a layer, each layer is cached and shared between images. Downloading ten images based on the same Debian downloads the base only once: that is what makes Docker so economical with downloads and disk.

Practical consequence: docker images shows the uncompressed size, but downloading only fetches the missing layers. Hence the value of shared bases — and of slim variants when they exist.

3. Choosing on Docker Hub without going wrong

Prefer official images (badge, verified maintainer), read the supported tags and the documentation, check the update date and the architecture (amd64 for PCs/servers, arm64 for M-series Macs and Raspberry Pi). An obscure image not updated for two years is a security risk, even if it saves 50 MB.

Idir applies the checklist to every new image: official, up to date, documented — the only ones accepted. The rest never reaches production.

Common misinterpretation: « latest = the best, and all images are equal as long as the name matches ». No. latest is a moving tag that can switch major version at the worst moment (silent drift), and a look-alike image abandoned for two years carries known vulnerabilities. Pin a precise tag of an official, verified, up-to-date image.
Choosing a trusted image Name, pinned tag, official source: the trusted image Official name VerifiedmaintainerPinned tag 16.4, notlatest in prodUp-to-date source Date +architecture checked
Name, pinned tag, official source: the trusted image
Text version of the diagram (SEO / screen readers / translation): 1) Name: Idir starts from the need (a Postgres database) and keeps the official image, not a copy with a similar name. 2) Pin: he picks tag 16.4 instead of latest and notes it in versions.txt. 3) Verify: update date and architecture (amd64/arm64) checked on Docker Hub before the first pull. Lesson: an official name, a pinned tag, an up-to-date source — and the same tag gives the same behavior six months later.

🔎 Concrete example — 🔎 Concrete example — Choosing Postgres well

Idir's choice for his application's database, with no latest in production.

docker pull postgres:16.4
docker images
# to avoid in production:
# docker run postgres:latest

Reading: we pin 16.4, check it is present locally, and ban latest from prod.

Lesson: six months later, the same tag gives the same behavior.

Section vocabulary

Tag
Version label after the « : » (16, 16.4, latest); it designates which variant of the image we fetch.

Simple example: Idir pins postgres:16.4 for his production database.

What it is not: a mere decorative comment.

Reflex: prod = pinned and noted tag, never latest.

Layer
Read-only stratum of the image, cached and shared between images.

Simple example: The Debian base downloaded once for ten images.

What it is not: a full copy duplicated per image.

Reflex: shared bases = downloads saved.

Official image
Image maintained and verified on Docker Hub (badge, identified maintainer).

Simple example: The official postgres chosen by Idir rather than an obscure copy.

What it is not: the first image with « postgres » in its name.

Reflex: official, up to date, documented — otherwise skip.

latest
Moving tag following the latest published version: handy in dev, unstable in prod.

Simple example: Idir uses it for testing, never for deploying.

What it is not: a pinned, reproducible version.

Reflex: latest in dev, precise tag in production.

In practice — In practice — Auditing your images

  1. List your local images (docker images) and spot the latest ones.
  2. For each one, find the equivalent pinned tag on Docker Hub.
  3. Check the architecture and update freshness.
  4. Write your choice (image:tag) in a versions.txt file.
Every image you use has a pinned, justified, noted tag.

Script ready to say — justifying your image (30 s)

« For the database, I take the official postgres image, pinned tag 16.4 — not latest, to stay reproducible. I checked the update date and the architecture on Docker Hub, and I note the choice in versions.txt for the team. »

Say while showing the Docker Hub page and the versions.txt file.

Copy-paste template — versions.txt

# versions.txt — Idir, Algiers
# One line per image: name:pinned tag + date of choice
postgres:16.4   # internal app database (chosen 2026-10)
nginx:1.27       # web frontend (chosen 2026-10)
# Rule: latest forbidden in prod. Every change = new dated line.

Idir's database

As above: official postgres:16.4, pinned and noted — the internal application's database runs identically on every machine.

Lightweight web frontend

Official nginx:1.27, slim variant if it covers the need: same checklist (official, up to date, architecture verified) before the first pull.

Laptop on arm64

Idir's colleague on an M-series Mac: check that the chosen tag really exists in arm64 on Docker Hub before promising reproducibility.

One-off tool image

ubuntu:24.04 in -it --rm for tinkering (level 1.2): even throwaway, pin the tag instead of latest to find the same tool tomorrow.

✓ Best practices

  • Pin in production, follow while exploring.
  • Prefer slim variants when they exist.
  • Read the Docker Hub page before the first pull.

✗ Common pitfalls

  • Deploying latest in production (silent drift).
  • Taking an abandoned image to save 50 MB.
  • Ignoring the architecture (amd64 image slow on M-series Macs).

Key takeaways

  • The tag pins the version; latest moves.
  • Layers are shared and cached.
  • Official, up to date, documented: the only ones accepted.
  • We note our versions like code.

48h challenge — apply tomorrow

List your images with docker images, track down the latest ones, find their pinned tag on Docker Hub (official, up to date, right architecture) and write your versions.txt.

Section exit checklist
  • I choose official, up-to-date, documented images.
  • I pin a precise tag in production (never latest).
  • I note each image:tag choice in versions.txt.
Self-assessment 1-5: does every image I use have a pinned, justified tag?did I check source, freshness and architecture before pulling?

Frequently asked questions

Alpine or slim, which to choose?

Both slim down: slim removes the useless from the official image, alpine changes libc (musl). Alpine is tiny but can surprise (DNS, perfs): test before prod. In both cases, pin the tag and check freshness.

How much does an image really weigh?

docker images gives the uncompressed size; downloading only fetches the missing layers. Hence the value of shared bases: stacking ten images on the same Debian costs the base only once.

Check your understanding

Which practice for a production database?

Additional resources (optional, to go further)

Level 1 examFresh, harder questions to test what you've learned