Pas 2 - Imatges: noms, capes i format
Al pas anterior vam descarregar hello-world, ubuntu:24.04 i alpine. Abans d'executar contenidors més seriosos, val la pena entendre què és exactament una imatge: com s'anomena, d'on ve, de què està feta i per què algunes descàrregues diuen Already exists.
Objectius del pas
- Descompondre el nom complet d'una imatge: registre, espai de noms, repositori, etiqueta i digest.
- Entendre que una etiqueta (tag) és mòbil i un digest és immutable.
- Veure que una imatge està formada per capes compartides entre imatges.
- Obrir una imatge i reconèixer el format estàndard OCI.
2.1 El nom complet d'una imatge
Quan escrivim nginx, Docker completa el nom amb valors per defecte. El nom complet té aquesta forma:
| Part | Exemple | Valor per defecte |
|---|---|---|
| Registre | docker.io, ghcr.io, quay.io, mcr.microsoft.com |
docker.io (Docker Hub) |
| Espai de noms | library, bitnami, el vostre usuari |
library (imatges oficials) |
| Repositori | nginx, mysql, hello-world |
obligatori |
| Etiqueta | 1.27-alpine, 8.4, latest |
latest |
| Digest | sha256:d715f14f... |
cap |
Per tant, aquestes comandes descarreguen exactament la mateixa imatge:
La primera la descarrega; les altres dues responen Image is up to date, perquè ja és local.
Alguns exemples reals per reconèixer cada part:
| Nom | Registre | Espai de noms | Repositori | Etiqueta |
|---|---|---|---|---|
mysql:8.4 |
docker.io | library | mysql | 8.4 |
bitnami/redis:7.4 |
docker.io | bitnami | redis | 7.4 |
ghcr.io/home-assistant/home-assistant:stable |
ghcr.io | home-assistant | home-assistant | stable |
mcr.microsoft.com/dotnet/aspnet:8.0 |
mcr.microsoft.com | dotnet | aspnet | 8.0 |
Quines imatges de Docker Hub són fiables?
A Docker Hub hi ha tres tipus d'imatges: Docker Official Images (espai library, mantingudes per Docker i els projectes originals), Verified Publisher (empreses verificades) i imatges de la comunitat (qualsevol usuari). Per defecte, feu servir imatges oficials o verificades. Podeu cercar-ne des del terminal amb docker search nginx, però la pàgina web mostra molta més informació: etiquetes disponibles, variables d'entorn i exemples d'ús.
2.2 Etiquetes: latest no vol dir "la més nova"
Una etiqueta és només una etiqueta de text que apunta a una imatge. Una mateixa imatge pot tenir diverses etiquetes alhora. Per exemple, en un moment donat, nginx:1.27, nginx:1.27.3, nginx:mainline i nginx:latest poden apuntar a la mateixa imatge.
Les etiquetes són mòbils: quan surt una versió nova, el mantenidor mou latest (i 1.27, mainline...) cap a la imatge nova. Per això:
latestés simplement l'etiqueta que es fa servir si no n'especifiqueu cap. No garanteix res.- Si dues persones fan
docker pull nginxamb un mes de diferència, poden obtenir imatges diferents. - En entorns reals, especifiqueu sempre una versió:
nginx:1.27-alpineen lloc denginx.
Moltes imatges ofereixen variants a l'etiqueta:
| Variant | Significat | Mida aproximada |
|---|---|---|
nginx:1.27 |
Basada en Debian | ~190 MB |
nginx:1.27-alpine |
Basada en Alpine Linux, molt lleugera | ~50 MB |
python:3.12 |
Debian completa amb eines de compilació | ~1 GB |
python:3.12-slim |
Debian mínima | ~130 MB |
Comproveu-ho vosaltres mateixos:
2.3 El digest: la identitat real de la imatge
Una etiqueta pot canviar, però el digest no. És un hash SHA-256 calculat a partir del contingut de la imatge: si canvia un sol byte, canvia el digest.
Podeu descarregar o executar una imatge pel seu digest, i tindreu la garantia que sempre serà exactament la mateixa:
IMAGE ID i digest no són el mateix
IMAGE ID és un identificador local (el hash de la configuració de la imatge). El digest (RepoDigests) identifica la imatge al registre. Tots dos són hashes SHA-256, però serveixen per a coses diferents.
2.4 Les capes
Recordeu la sortida d'un docker pull d'una imatge gran:
1.27: Pulling from library/nginx
a2318d6c47ec: Pull complete
095d327c79ae: Pull complete
bbfaa25db775: Pull complete
7bb6fb0cfb2b: Pull complete
0723edc10c17: Pull complete
24b3fdc4d1e3: Pull complete
3122471704d5: Pull complete
Digest: sha256:...
Cada línia és una capa. Una imatge no és un únic fitxer gegant, sinó una pila de capes de només lectura. Cada capa conté els fitxers que s'han afegit, modificat o eliminat respecte de la capa anterior:
flowchart TB
W["Capa d escriptura del contenidor (lectura i escriptura)"]
L3["Capa 3 - configuracio de nginx"]
L2["Capa 2 - paquets de nginx"]
L1["Capa 1 - sistema base Debian"]
W --- L3 --- L2 --- L1
classDef rw fill:#16A34A,stroke:#166534,color:#FFFFFF
classDef ro fill:#2563EB,stroke:#1E40AF,color:#FFFFFF
class W rw
class L1,L2,L3 ro
Quan arrenqueu un contenidor, Docker hi afegeix una capa d'escriptura a sobre. Tot el que el contenidor modifica va a parar a aquesta capa; la imatge de sota no canvia mai. Per això de la mateixa imatge en podeu arrencar deu contenidors: comparteixen les capes de lectura i cadascun té la seva capa d'escriptura.
Les capes es comparteixen
Proveu això:
En la segona descàrrega veureu línies com aquestes:
Already exists vol dir que aquella capa (el sistema base Debian) ja era al disc perquè l'havia portat la primera imatge. Docker no la torna a descarregar ni la desa dues vegades. Aquest mecanisme estalvia molt d'espai i ample de banda.
Inspeccionar les capes
Mostra cada capa, la instrucció que la va crear i la seva mida. És el primer contacte amb les instruccions d'un Dockerfile (RUN, COPY, CMD...), que escriurem nosaltres al Pas 8.
Per veure totes les metadades de la imatge (capes, variables d'entorn, ordre per defecte, ports declarats...):
docker image inspect nginx:1.27-alpine
docker image inspect --format '{{.Config.Cmd}}' nginx:1.27-alpine
docker image inspect --format '{{.Os}}/{{.Architecture}}' nginx:1.27-alpine
2.5 El format d'una imatge per dins: OCI
Les imatges segueixen un estàndard obert, l'OCI Image Format Specification de l'Open Container Initiative. Per això una imatge construïda amb Docker es pot executar amb Podman, containerd o Kubernetes.
Podem exportar una imatge a un fitxer .tar i mirar-ne el contingut:
mkdir /tmp/imatge && cd /tmp/imatge
docker save hello-world:latest -o hello.tar
tar -xf hello.tar
ls -R
.:
blobs hello.tar index.json manifest.json oci-layout repositories
./blobs/sha256:
03b62250a3cb... 74cc54e27dc4... e6590344b1a5... ...
| Element | Contingut |
|---|---|
oci-layout |
Declara que el directori segueix el format OCI |
index.json |
Punt d'entrada: apunta al manifest de la imatge |
blobs/sha256/ |
Tots els objectes, cadascun anomenat pel seu hash |
| Manifest (un blob JSON) | Llista la configuració i les capes, amb els seus digests |
| Configuració (un blob JSON) | Arquitectura, variables d'entorn, Cmd, Entrypoint, historial... |
Capes (blobs tar o tar.gz) |
Els fitxers de cada capa |
Podeu llegir els JSON amb cat (o millor, amb jq si el teniu instal·lat) i descomprimir una capa amb tar -tf blobs/sha256/<hash> per veure'n els fitxers. Al cas de hello-world hi trobareu un únic fitxer: el binari /hello.
flowchart LR
IDX[index.json] --> M[Manifest]
M --> CFG[Configuracio JSON]
M --> C1[Capa 1 tar]
M --> C2[Capa 2 tar]
M --> C3[Capa N tar]
classDef a fill:#7C3AED,stroke:#5B21B6,color:#FFFFFF
classDef b fill:#2563EB,stroke:#1E40AF,color:#FFFFFF
classDef c fill:#16A34A,stroke:#166534,color:#FFFFFF
class IDX,M a
class CFG b
class C1,C2,C3 c
Imatges multiarquitectura
Moltes imatges oficials existeixen per a diverses arquitectures (amd64, arm64...). Al registre hi ha un índex que apunta a un manifest per a cada arquitectura, i Docker descarrega automàticament el que correspon a la vostra màquina. Per això docker pull nginx funciona igual en un PC i en un Mac amb processador Apple Silicon o en una Raspberry Pi.
Miniactivitat - Anatomia d'una imatge
- Escriviu el nom complet (registre, espai de noms, repositori i etiqueta) de
mysql,bitnami/postgresql:16ighcr.io/linuxserver/nginx. - Descarregueu
nginx:1.27inginx:1.27-alpine. Quina diferència de mida hi ha? Quantes capes té cadascuna (docker image history)? - Descarregueu
python:3.12-slimi despréspython:3.13-slim. Quantes capes surten com aAlready exists? - Exporteu
alpine:3.20ambdocker save, obriu el manifest i indiqueu quantes capes té i quin és elCmdper defecte que trobeu a la configuració.
2.6 Neteja d'imatges
docker rmi nginx:1.27 # elimina una imatge (o una etiqueta)
docker image prune # elimina les imatges "penjades" (sense etiqueta)
docker image prune -a # elimina totes les imatges que no fa servir cap contenidor
docker system df # espai ocupat per imatges, contenidors i volums
No es pot eliminar una imatge en ús
Si algun contenidor (fins i tot aturat) s'ha creat a partir d'una imatge, docker rmi fallarà. Primer cal eliminar el contenidor. Si una imatge té diverses etiquetes, docker rmi només treu l'etiqueta indicada fins que no en queda cap.
Resum del pas
| Concepte | Idea clau |
|---|---|
| Nom complet | registre/espai/repositori:etiqueta@digest; per defecte docker.io/library/...:latest |
| Etiqueta | Nom mòbil; especifiqueu sempre una versió concreta |
| Digest | Hash immutable del contingut |
| Capes | Pila de capes de només lectura, compartides entre imatges |
| Capa d'escriptura | La que afegeix cada contenidor; desapareix amb el contenidor |
| OCI | Format estàndard: índex, manifest, configuració i capes |
Següent pas: fins ara els contenidors s'aturaven de seguida. Al Pas 3 arrencarem un servidor que es queda funcionant en segon pla.