1.1Images: tags, layers and Docker Hub
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.
🔎 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
- List your local images (docker images) and spot the latest ones.
- For each one, find the equivalent pinned tag on Docker Hub.
- Check the architecture and update freshness.
- Write your choice (image:tag) in a versions.txt file.
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.
- 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.
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.
Which practice for a production database?