Has descarregat imatges, les has llistat i les has esborrat, però encara no saps què són per dins. I aquest "per dins" explica gairebé tot el que et sorprendrà de Docker als propers mòduls: per què descarregar la segona imatge és més ràpid que la primera, per què la suma de mides de docker images no quadra amb el disc realment ocupat, per què les dades que escrius dins d'un contenidor desapareixen en esborrar-lo, i per què l'etiqueta latest és un parany. En aquesta lliçó disseccionaràs una imatge: la seva naturalesa immutable, el seu model de capes, el mecanisme de copy-on-write que separa la imatge del contenidor, la nomenclatura completa amb registres i digests, les famílies d'imatges base, i una exploració pràctica amb docker image history i inspect sobre node:22-alpine, que serà la base de l'API d'Aurora Libros.
Contingut
- Què és exactament una imatge
- El model de capes
- La capa d'escriptura del contenidor i el copy-on-write
- La conseqüència clau: les dades es perden
- Nomenclatura completa: registre, repositori, etiqueta i digest
- Per què
latestno significa "l'última" - Imatges base i variants oficials
- Exploració pràctica amb
node:22-alpine - Comprovant que dues imatges comparteixen capes
- Què és exactament una imatge
Una imatge de Docker són dues coses empaquetades juntes:
- Un sistema de fitxers: el conjunt complet de directoris i fitxers que veurà l'aplicació quan s'executi. Binaris, llibreries, fitxers de configuració, el teu codi.
- Unes metadades d'arrencada: com s'ha d'executar. Quina comanda llançar, amb quines variables d'entorn, quin usuari, en quin directori de treball, quins ports declara.
I té tres propietats que defineixen el seu comportament:
- És immutable. Un cop construïda, no canvia mai. Si necessites una versió diferent, en construeixes una altra.
- És de només lectura. Cap contenidor no hi pot escriure.
- És identificable de manera criptogràfica. El seu contingut produeix un hash SHA-256 que la identifica sense ambigüitat.
Aquestes tres propietats juntes són les que fan possible la reproduïbilitat: si dues màquines executen la imatge amb el mateix digest, estan executant exactament els mateixos bytes.
El que una imatge no conté, i convé tenir clar des del principi:
| Sí que conté | No conté |
|---|---|
| Binaris i llibreries d'espai d'usuari | Un nucli (fa servir el de l'amfitrió) |
| Fitxers de configuració | Dades de la teva base de dades en producció |
| El teu codi d'aplicació | Secrets que hagin de variar per entorn |
| Metadades: comanda, variables, usuari, ports | Estat d'execució |
- El model de capes
Aquí hi ha la idea central. Una imatge no és un bloc monolític: és una pila de capes, cadascuna de les quals és un diff, un conjunt de canvis respecte a la capa anterior.
Imagina't com es construeix la imatge de l'API d'Aurora Libros:
- Capa 1: el sistema de fitxers base d'Alpine Linux (uns 8 MB).
- Capa 2: a sobre, s'hi instal·la Node.js 22 (s'hi afegeixen fitxers nous).
- Capa 3: a sobre, s'hi copia el
package.jsondel projecte. - Capa 4: a sobre, s'hi instal·len les dependències d'npm (
node_modules). - Capa 5: a sobre, s'hi copia el codi de l'API.
graph TB
subgraph IMG["Imatge aurora-api:1.0.0 (només lectura)"]
L5["Capa 5 · codi de l'API · 120 KB"]
L4["Capa 4 · node_modules · 48 MB"]
L3["Capa 3 · package.json · 2 KB"]
L2["Capa 2 · Node.js 22 · 42 MB"]
L1["Capa 1 · Alpine Linux base · 8 MB"]
end
L1 --- L2 --- L3 --- L4 --- L5
Quan el contenidor arrenca, totes aquestes capes es fusionen en una sola vista unificada del sistema de fitxers gràcies a un union filesystem (en Linux modern, overlay2, el driver que vas veure a docker info). Des de dins del contenidor no perceps capes: veus un / normal amb /usr, /etc, /app, etc.
Les regles de la fusió són simples:
- Un fitxer que només existeix en una capa, hi apareix.
- Si un fitxer existeix en diverses capes, guanya el de la capa superior.
- Si una capa esborra un fitxer d'una d'inferior, es marca amb un fitxer especial whiteout i deixa de veure's (però continua ocupant espai a la capa inferior; aquesta conseqüència és important per a la mida de les imatges i s'explota a la lliçó 05-04).
I ara la propietat que ho fa tot eficient: les capes es comparteixen entre imatges. Si tens cinc imatges diferents construïdes sobre node:22-alpine, les capes d'Alpine i de Node s'emmagatzemen una sola vegada al disc i les cinc imatges les referencien.
graph TB
BASE["Capa: Alpine 3.20"] --> NODE["Capa: Node.js 22"]
NODE --> API1["aurora-api:1.0.0<br/>+ 2 capes pròpies"]
NODE --> API2["aurora-api:1.1.0<br/>+ 2 capes pròpies"]
NODE --> WORKER["aurora-worker:1.0.0<br/>+ 3 capes pròpies"]
D'aquí en surten tres beneficis molt concrets:
- Estalvi de disc: no multipliques la base per cada imatge.
- Descàrregues ràpides: en fer
pullde la segona imatge, el daemon només baixa les capes que li falten. Per això de vegades veusAlready existsen lloc dePull complete. - Pujades ràpides: en publicar una versió nova de la teva API en què només va canviar el codi, només es puja aquesta capa.
Aquest últim punt tindrà conseqüències enormes quan escriguis el teu primer Dockerfile al mòdul 2: l'ordre de les instruccions determina quines capes es reaprofiten.
- La capa d'escriptura del contenidor i el copy-on-write
Si la imatge és de només lectura, com pot un contenidor escriure fitxers? La resposta és la peça que uneix els dos conceptes:
Quan crees un contenidor, Docker apila una capa fina de lectura i escriptura a sobre de les capes de només lectura de la imatge. Aquesta capa pertany només a aquell contenidor.
graph TB
subgraph C1["Contenidor A"]
WA["Capa d'escriptura A<br/>(lectura/escriptura)"]
end
subgraph C2["Contenidor B"]
WB["Capa d'escriptura B<br/>(lectura/escriptura)"]
end
subgraph IMG["Imatge nginx:alpine (només lectura, COMPARTIDA)"]
I3["Capa 3"]
I2["Capa 2"]
I1["Capa 1"]
end
WA --> I3
WB --> I3
I3 --- I2 --- I1
Dos contenidors de la mateixa imatge comparteixen totes les capes de la imatge i només tenen pròpia la seva capa superior. Per això arrencar el desè contenidor d'una imatge no costa pràcticament disc.
El mecanisme que fa això possible s'anomena copy-on-write (copiar en escriure), i funciona així:
| Operació dins del contenidor | Què passa realment |
|---|---|
| Llegir un fitxer de la imatge | Es llegeix directament de la capa de la imatge. Cost zero |
| Crear un fitxer nou | Es crea a la capa d'escriptura del contenidor |
| Modificar un fitxer de la imatge | Es copia sencer a la capa d'escriptura i es modifica allà. La imatge no es toca |
| Esborrar un fitxer de la imatge | Es marca com a esborrat a la capa d'escriptura (whiteout). Continua existint a la imatge |
Conseqüències pràctiques que notaràs:
- Modificar un fitxer gran per primera vegada és lent, perquè cal copiar-lo sencer abans. Les vegades següents ja és ràpid.
- Les aplicacions amb escriptura intensiva (bases de dades, precisament) rendeixen pitjor si escriuen a la capa del contenidor. La solució és fer servir volums, i per això
aurora-dben necessitarà un.
Pots veure la mida d'aquesta capa d'escriptura:
Com es llegeix: 1.09kB és el que ha escrit aquest contenidor a la seva capa pròpia; virtual 52.5MB és el total incloent-hi les capes de la imatge, que són compartides. Si arrenques cinc contenidors de nginx:alpine, el disc no creix 5 × 52,5 MB, sinó 52,5 MB més cinc capes d'escriptura minúscules.
- La conseqüència clau: les dades es perden
Aquesta és la implicació pràctica més important de tot l'apartat anterior, i mereix el seu propi bloc perquè és la causa de la majoria dels ensurts dels principiants:
La capa d'escriptura viu i mor amb el contenidor. Quan esborres un contenidor, la seva capa d'escriptura s'esborra amb ell. Tot el que l'aplicació hi hagués escrit desapareix per sempre.
Comprova-ho tu mateix, pas a pas:
docker run --name prova-dades alpine:3.20 \
sh -c "echo 'Catàleg Aurora Libros' > /dades.txt && cat /dades.txt"El contenidor ha escrit el fitxer a la seva capa d'escriptura i l'ha mostrat. Ara reprèn aquest mateix contenidor amb docker start -a (la -a és --attach, per veure'n la sortida):
Continua funcionant: la capa d'escriptura del contenidor persisteix mentre el contenidor existeixi, encara que estigui aturat. I ara la part reveladora:
Què acaba de passar: en esborrar el contenidor va desaparèixer la seva capa d'escriptura i amb ella /dades.txt. El contenidor nou neix de la imatge, que mai no va contenir aquest fitxer. La imatge és immutable: escriure dins d'un contenidor no modifica la imatge.
Traduït a Aurora Libros: si fiques PostgreSQL en un contenidor sense més i esborres aquest contenidor, perds el catàleg de llibres sencer. En un entorn de desenvolupament és molest; en producció és un incident greu.
La solució s'anomena volums: emmagatzematge que viu fora del cicle de vida del contenidor. És el tema complet de la lliçó 03-06, i a la lliçó 01-06 faràs un primer ús molt introductori de -v per servir una pàgina d'Aurora Libros amb Nginx. De moment, queda't amb la regla:
Tota dada que hagi de sobreviure al contenidor ha d'estar en un volum.
- Nomenclatura completa: registre, repositori, etiqueta i digest
Quan escrius nginx:alpine, estàs fent servir una forma abreujada. El nom complet d'una imatge és:
Exemples, de més abreujat a més explícit:
| El que escrius | Com ho resol Docker |
|---|---|
nginx |
docker.io/library/nginx:latest |
nginx:alpine |
docker.io/library/nginx:alpine |
bitnami/postgresql:16 |
docker.io/bitnami/postgresql:16 |
ghcr.io/aurora-libros/aurora-api:1.2.0 |
Tal qual: registre GitHub, organització, repositori, etiqueta |
registry.auroralibros.local:5000/aurora-api:1.2.0 |
Registre privat al port 5000 |
Les regles d'emplenat automàtic són:
- Si no indiques registre, s'assumeix
docker.io(Docker Hub). - Si no indiques usuari o organització i el registre és Docker Hub, s'assumeix
library/, l'espai reservat a les imatges oficials. Per aixònginxés oficial ibitnami/postgresqlés d'un tercer. - Si no indiques etiqueta, s'assumeix
:latest.
El digest
A més de per nom i etiqueta, tota imatge té un digest: el hash SHA-256 del seu manifest.
REPOSITORY TAG DIGEST IMAGE ID SIZE
nginx alpine sha256:c15da6c91de8d2f436196f3a768483ad32c258ed4e1beb3d367a27ed67253e66 3f8a4339aadd 52.5MBLa diferència entre els tres identificadors:
| Identificador | Exemple | Naturalesa |
|---|---|---|
| Etiqueta | nginx:alpine |
Mutable: es pot reassignar a una altra imatge en qualsevol moment |
| Image ID | 3f8a4339aadd |
Hash local de la configuració; immutable, però només té sentit a la teva màquina |
| Digest | sha256:c15da6c9... |
Immutable i global: identifica exactament els mateixos bytes a qualsevol registre i màquina |
I per això pots ancorar una imatge sense cap ambigüitat:
Això descarrega aquella imatge exacta, passi el que passi amb les etiquetes. És la pràctica recomanada en producció i en pipelines de CI, on la reproduïbilitat importa més que la comoditat. Ho reprendrem a les lliçons 02-06 i 06-01.
- Per què
latest no significa "l'última"
latest no significa "l'última"Aquest és un dels malentesos més cars de Docker, així que serem taxatius:
latestno és una funció que retorni la versió més recent. És simplement el nom d'etiqueta que Docker fa servir per defecte quan no n'especifiques cap.
Res no obliga que latest apunti a l'última versió. És una convenció, i una convenció que s'incompleix amb freqüència:
- Un mantenidor pot publicar
2.0.0sense actualitzarlatest, que es queda a la 1.x. - Alguns projectes fan servir
latestper a l'última versió estable i publiquen les noves majors només amb el seu número. - I a l'inrevés:
latestpot apuntar a una versió de desenvolupament inestable.
Els problemes concrets que causa fer-la servir:
| Problema | Explicació |
|---|---|
| No reproduïble | docker pull lamevaapp:latest avui i demà poden portar imatges diferents. El teu CI pot passar avui i fallar demà sense que ningú hagi tocat el codi |
| Actualitzacions silencioses | Un canvi major amb ruptura de compatibilitat pot entrar al teu desplegament sense que ho decideixis |
| Memòria cau enganyosa | Si ja tens latest en local, Docker no torna a comprovar el registre llevat que forcis el pull. Pots estar executant una versió de fa mesos creient que és l'última |
| Diagnòstic impossible | "Quina versió hi ha en producció?" — "latest". Això no és cap resposta |
La pràctica correcta:
# Malament: no saps què estàs executant
docker pull node
# Millor: versió major i variant fixades
docker pull node:22-alpine
# Encara millor per a producció: versió concreta
docker pull node:22.14.0-alpine3.21
# Màxim rigor: ancorat per digest
docker pull node:22-alpine@sha256:9d2b8c0...Regla pràctica: en desenvolupament, node:22-alpine és un equilibri raonable entre estabilitat i comoditat. En producció i CI, versió completa o digest. Durant el curs farem servir etiquetes explícites sempre: node:22-alpine, postgres:16-alpine, redis:7-alpine, nginx:alpine.
- Imatges base i variants oficials
Una imatge base és el punt de partida sobre el qual construeixes. Aquestes són les famílies que trobaràs:
| Imatge base | Mida aprox. | Gestor de paquets | Libc | Quan fer-la servir |
|---|---|---|---|---|
scratch |
0 bytes | Cap | Cap | Binaris estàtics (Go, Rust). Màxima seguretat i mínima mida |
alpine |
~8 MB | apk |
musl | Per defecte quan la mida importa |
debian:bookworm-slim |
~75 MB | apt |
glibc | Compatibilitat àmplia amb mida continguda |
debian:bookworm |
~120 MB | apt |
glibc | Quan necessites eines del sistema |
ubuntu:24.04 |
~78 MB | apt |
glibc | Familiaritat, paquets d'Ubuntu |
| Imatges distroless | ~20 MB | Cap | glibc | Producció endurida, sense shell |
Un avís important sobre Alpine: fa servir musl com a llibreria de C en lloc de la glibc habitual. El 95 % de les vegades tant se val, però pot causar problemes amb paquets de Python o de Node que portin binaris compilats contra glibc, i en casos concrets hi ha diferències de rendiment en la resolució de noms DNS. Si alguna cosa es comporta de manera estranya a Alpine i no a Debian, aquesta sol ser la causa.
Variants de les imatges oficials de llenguatges
Les imatges oficials publiquen diverses variants de cada versió, i triar bé és important. Prenguem Node.js 22, que és el que necessitarà aurora-api:
| Etiqueta | Base | Mida aprox. | Comentari |
|---|---|---|---|
node:22 |
Debian complet | ~1,1 GB | Porta compiladors i eines. Còmoda, enorme |
node:22-slim |
debian:slim |
~230 MB | Debian sense extres. Bon equilibri |
node:22-alpine |
Alpine | ~140 MB | La més petita amb gestor de paquets. La que farem servir |
node:22-bookworm |
Debian 12 | ~1,1 GB | Igual que node:22 però fixant la versió de Debian |
Les bases de dades segueixen el mateix patró: postgres:16 (Debian) davant de postgres:16-alpine, i redis:7 davant de redis:7-alpine.
I una recomanació de seguretat que prendrà tot el seu sentit a la lliçó 05-03: prefereix sempre imatges oficials o verificades. Qualsevol pot publicar a Docker Hub una imatge anomenada postgresql-rapid amb el que li vingui de gust a dins.
- Exploració pràctica amb
node:22-alpine
node:22-alpineDisseccionem la imatge que serà la base d'aurora-api.
Descarregar-la
22-alpine: Pulling from library/node
f18232174bc9: Already exists
9c3b5e8d1a2f: Pull complete
7d4a2c9e0f31: Pull complete
b1e6f8a4c507: Pull complete
Digest: sha256:9d2b8c0f4e1a7b3d5c6e8f0a2b4d6e8f0a1c3e5d7f9b1d3f5a7c9e1b3d5f7a9c
Status: Downloaded newer image for node:22-alpine
docker.io/library/node:22-alpineFixa't en la primera línia de capes: Already exists. Aquesta capa (f18232174bc9) és el sistema base d'Alpine, i ja la tenies del docker pull alpine:3.20 de la lliçó anterior. Docker no l'ha tornada a descarregar. Acabes de veure la compartició de capes en funcionament.
Llistar-la
Veure el seu historial de capes
IMAGE CREATED CREATED BY SIZE COMMENT
c4b8e2f1a9d3 5 days ago CMD ["node"] 0B
<missing> 5 days ago ENTRYPOINT ["docker-entrypoint.sh"] 0B
<missing> 5 days ago COPY docker-entrypoint.sh /usr/local/bin/ #… 388B
<missing> 5 days ago RUN /bin/sh -c apk add --no-cache --virtual … 7.66MB
<missing> 5 days ago ENV YARN_VERSION=1.22.22 0B
<missing> 5 days ago RUN /bin/sh -c addgroup -g 1000 node && addu… 125MB
<missing> 5 days ago ENV NODE_VERSION=22.14.0 0B
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:8f4a3d2b1c… in / 8.83MBEs llegeix de baix a dalt, en ordre de construcció. Anem amb les claus:
- L'última línia (
ADD file:... in /, 8,83 MB) és la capa base d'Alpine. Coincideix exactament amb la mida d'alpine:3.20que vas veure abans: és literalment la mateixa capa. RUN ... addgroup ... 125MBés la instal·lació de Node.js: la capa més pesada amb diferència. Aquí hi ha el gruix dels 142 MB.- Les capes de 0B (
ENV,CMD,ENTRYPOINT) no afegeixen fitxers: només modifiquen les metadades d'arrencada. Ocupen zero perquè no canvien el sistema de fitxers. <missing>a la columna IMAGE no és cap error: significa que aquesta capa intermèdia no té un ID d'imatge propi a la teva màquina, perquè vas descarregar la imatge en lloc de construir-la. És completament normal.
Per veure la sortida sense truncar:
Inspeccionar-ne les metadades
Retorna un JSON llarg. Extraiem-ne l'important:
{
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NODE_VERSION=22.14.0",
"YARN_VERSION=1.22.22"
],
"Cmd": ["node"],
"Entrypoint": ["docker-entrypoint.sh"],
"WorkingDir": "",
"Labels": null
}Aquestes són les metadades d'arrencada de l'apartat 1:
Env: variables d'entorn que tindrà tot contenidor d'aquesta imatge.Cmd: la comanda per defecte. Si fasdocker run node:22-alpinesense més, executanodei t'obre la seva consola interactiva.Entrypoint: un script que s'executa abans i que repCmdcom a argument.WorkingDir: el directori de treball inicial.
La distinció entre Cmd i Entrypoint és subtil i important, i es tracta a fons a la lliçó 02-04.
Altres camps útils:
docker image inspect node:22-alpine --format 'Arquitectura: {{.Architecture}} / SO: {{.Os}}'
docker image inspect node:22-alpine --format 'Capes: {{len .RootFS.Layers}}'
docker image inspect node:22-alpine --format '{{range .RootFS.Layers}}{{println .}}{{end}}'Arquitectura: amd64 / SO: linux
Capes: 4
sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870
sha256:9c3b5e8d1a2f...
sha256:7d4a2c9e0f31...
sha256:b1e6f8a4c507...L'última comanda llista els hashes de les capes de la imatge. Guarda't el primer d'aquesta llista: el compararàs a l'apartat següent.
- Comprovant que dues imatges comparteixen capes
Demostrem la compartició de manera inequívoca. Primer, assegura't de tenir les dues imatges:
Ara compara'n les llistes de capes:
sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870
sha256:9c3b5e8d1a2f...
sha256:7d4a2c9e0f31...
sha256:b1e6f8a4c507...La primera capa és idèntica en totes dues. Mateix hash, mateixos bytes, emmagatzemats una sola vegada a /var/lib/docker/overlay2. La imatge de Node no conté la seva pròpia còpia d'Alpine: la referencia.
Pots automatitzar la comparació:
comm -12 \
<(docker image inspect alpine:3.20 --format '{{range .RootFS.Layers}}{{println .}}{{end}}' | sort) \
<(docker image inspect node:22-alpine --format '{{range .RootFS.Layers}}{{println .}}{{end}}' | sort)Què fa: comm -12 compara dues llistes ordenades i mostra només les línies comunes (suprimeix les exclusives de la primera amb -1 i les de la segona amb -2). Els <(...) són substitucions de procés de bash: passen la sortida de cada comanda com si fos un fitxer. El resultat és la llista de capes compartides.
I la confirmació en xifres:
REPOSITORY TAG IMAGE ID SIZE
node 22-alpine c4b8e2f1a9d3 142MB
nginx alpine 3f8a4339aadd 52.5MB
alpine 3.20 a8560b36e8b8 8.83MBSuma les tres imatges: 142 + 52,5 + 8,83 = 203,3 MB. Però docker system df reporta 194,5 MB. La diferència de gairebé 9 MB és exactament la capa base d'Alpine, comptada tres vegades a docker image ls i una sola vegada al disc.
Aquí tens la resposta a una de les preguntes del principi de la lliçó: la columna SIZE de docker image ls mostra la mida total de cada imatge, sense descomptar el que és compartit. Per saber l'espai real, fes servir docker system df.
Errors Habituals i Consells
- Creure que es pot modificar una imatge. No es pot: és immutable. El que escrius dins d'un contenidor va a la seva capa d'escriptura, no a la imatge. Per "canviar" una imatge se'n construeix una altra (mòdul 2).
- Perdre dades per no fer servir volums. És *l'*error clàssic. Si el teu contenidor de PostgreSQL guarda el catàleg d'Aurora Libros a la seva capa d'escriptura, un
docker rmho esborra tot. Solució: volums (lliçó 03-06). - Fer servir
latesten qualsevol lloc seriós. No significa "l'última", no és reproduïble i fa impossible respondre a "quina versió hi ha desplegada". Fixa etiquetes explícites, i digests en producció. - Sumar la columna SIZE de
docker image ls. Dona un número més gran que el real per les capes compartides. Fes servirdocker system df. - Pensar que esborrar un fitxer en una capa redueix la mida de la imatge. No: la capa inferior continua contenint-lo, només s'oculta. És la raó que una imatge mal construïda pesi de més (lliçó 05-04).
- Confondre Image ID i digest. L'Image ID és local; el digest és global i és el que has de fer servir per ancorar una versió exacta.
- Consell:
docker image historyabans que qualsevol optimització. Et diu d'un cop d'ull quina capa està engreixant la imatge. - Consell: tria la variant correcta.
node:22pesa unes vuit vegades més quenode:22-alpine. En un pipeline que construeix vint vegades al dia, aquesta diferència es nota en temps i en factura.
Exercicis
Exercici 1: l'aritmètica de les capes
Descarrega aquestes tres imatges i respon:
- Quant sumen les mides que mostra
docker image ls? - Quant ocupen realment al disc segons
docker system df? - Explica la diferència identificant quina capa concreta (per hash) n'és la responsable.
- A la sortida dels
pull, en quins van aparèixer líniesAlready existsi per què?
Exercici 2: la lliçó de la persistència
Executa aquesta seqüència i explica el resultat de cada pas:
docker run --name llibres alpine:3.20 sh -c "echo 'Rayuela, Julio Cortazar' > /cataleg.txt && cat /cataleg.txt"
docker start -a llibres
docker rm llibres
docker run --name llibres alpine:3.20 cat /cataleg.txtDesprés respon: (a) per què la segona comanda sí que troba el fitxer i la quarta no?, (b) en quin moment exacte es va perdre la dada?, (c) què hauria passat si en lloc de docker rm només haguessis fet docker stop?
Exercici 3: identifica una imatge sense ambigüitat
Per a la imatge node:22-alpine de la teva màquina, obtén: (a) el seu Image ID, (b) el seu digest, (c) el nombre de capes que té, (d) la seva comanda per defecte i les seves variables d'entorn, i (e) la mida de la capa més gran i quina instrucció la va generar. Després, escriu la comanda docker pull que descarregaria exactament aquesta mateixa imatge d'aquí a dos anys, encara que l'etiqueta 22-alpine hagi canviat de contingut.
Solucions
Solució a l'exercici 1
- La suma de la columna SIZE rondarà els 200 MB (aproximadament 8,8 + 142 + 41 segons versions).
docker system dfreportarà una xifra menor, uns 9 MB per sota de la suma.- La responsable és la capa base d'Alpine. Verifica-ho així:
for img in alpine:3.20 node:22-alpine redis:7-alpine; do
echo "$img:"
docker image inspect $img --format '{{index .RootFS.Layers 0}}'
doneAquest bucle imprimeix la primera capa de cada imatge (index .RootFS.Layers 0 pren l'element 0 de l'array). Les tres mostren el mateix sha256:f1823217...: és la mateixa capa física emmagatzemada una vegada i referenciada tres vegades. docker image ls la compta a cada imatge; docker system df la compta un cop, i d'aquí la diferència.
Already existsapareix al segon i al tercerpullper a aquesta capa base. Al primer (alpine:3.20) es va haver de descarregar; a partir d'aquí, el daemon comprova el hash, veu que ja la té i se la salta. Aquesta és la raó pràctica que les descàrregues successives d'imatges de la mateixa família siguin molt més ràpides.
Solució a l'exercici 2
Pas a pas:
docker run --name llibres ...crea un contenidor nou, escriu/cataleg.txta la seva capa d'escriptura i el mostra. Sortida:Rayuela, Julio Cortazar. El contenidor acaba i queda enExited (0).docker start -a llibresreprèn el mateix contenidor (no en crea un altre). Torna a executar la seva comanda, que reescriu i mostra el fitxer. La capa d'escriptura continuava intacta.docker rm llibreselimina el contenidor i la seva capa d'escriptura amb ell./cataleg.txtdeixa d'existir.docker run --name llibres alpine:3.20 cat /cataleg.txtcrea un contenidor nou a partir de la imatge. Sortida:
Respostes:
(a) La segona comanda troba el fitxer perquè opera sobre el mateix contenidor, la capa d'escriptura del qual persisteix mentre el contenidor existeixi. La quarta no el troba perquè opera sobre un contenidor diferent, nascut de la imatge alpine:3.20, que mai no va contenir aquest fitxer. Escriure dins d'un contenidor no modifica la imatge: la imatge és immutable.
(b) La dada es va perdre exactament al docker rm. Aquest és el moment en què la capa d'escriptura s'elimina del disc.
(c) Amb docker stop el fitxer hi continuaria sent. Aturar un contenidor atura el seu procés però conserva la seva capa d'escriptura; un docker start -a llibres posterior hauria tornat a mostrar el contingut. Només rm destrueix les dades. Aquesta distinció entre "aturat" i "eliminat" és central en el cicle de vida que veuràs a la lliçó 03-02.
Solució a l'exercici 3
# (a) Image ID
docker image inspect node:22-alpine --format '{{.Id}}'
# (b) Digest
docker image inspect node:22-alpine --format '{{index .RepoDigests 0}}'
# (c) Nombre de capes
docker image inspect node:22-alpine --format '{{len .RootFS.Layers}}'
# (d) Comanda per defecte i variables d'entorn
docker image inspect node:22-alpine --format 'Cmd: {{.Config.Cmd}}{{println}}Env: {{.Config.Env}}'
# (e) Capa més gran i la seva instrucció
docker image history node:22-alpine --no-trunc --format "{{.Size}}\t{{.CreatedBy}}" | sort -h -r | head -1Comentaris:
.Idretorna l'Image ID complet amb prefixsha256:; els 12 primers caràcters són els que veus adocker image ls..RepoDigestsés un array perquè una imatge pot estar publicada en diversos repositoris;index ... 0en pren el primer. El format ésnode@sha256:....len .RootFS.Layerscompta els elements de l'array de capes: normalment 4 per a aquesta imatge.- La capa més gran serà la del
RUNque instal·la Node.js, al voltant de 125 MB. Aquesta única línia explica la major part de la mida de la imatge.
La comanda que descarrega exactament aquesta imatge d'aquí a dos anys:
Substituint el digest pel que t'hagi retornat l'apartat (b). La clau del raonament: l'etiqueta 22-alpine és un punter mutable que el mantenidor pot reassignar a una imatge diferent cada vegada que publiqui un pedaç de Node 22. El digest, en canvi, és el hash del contingut: identifica aquests bytes concrets i res més. Mentre la imatge continuï existint al registre, aquest pull portarà sempre el mateix. És la pràctica estàndard per a la reproduïbilitat en CI i producció.
Conclusió
Una imatge és un sistema de fitxers més unes metadades d'arrencada, immutable, de només lectura i identificada criptogràficament. Internament és una pila de capes, cadascuna un diff de l'anterior, que es fusionen en una vista única i —això és l'important— es comparteixen entre imatges, d'on surten les descàrregues incrementals i l'estalvi de disc que has verificat amb les teves pròpies mans comparant els hashes d'alpine:3.20 i node:22-alpine.
En crear un contenidor, Docker hi afegeix a sobre una capa d'escriptura pròpia i aplica copy-on-write: llegir és gratis, modificar implica copiar. I d'aquí la regla que més disgustos evita: aquesta capa mor amb el contenidor, així que tota dada que hagi de sobreviure ha d'anar a un volum (lliçó 03-06).
També ja saps anomenar imatges amb precisió —registre/usuari/repositori:etiqueta@digest—, per què latest és un nom i no una promesa, i quines famílies d'imatges base existeixen, inclosa node:22-alpine, que serà la base de l'API d'Aurora Libros.
Amb la teoria d'imatges resolta, ja no hi ha res que t'impedeixi embrutar-te les mans. A la lliçó següent, Creant el teu Primer Contenidor Docker, faràs una pràctica guiada completa: un contenidor en primer pla, un servidor Nginx en segon pla amb el seu port publicat, un shell interactiu dins d'Alpine, i la teva primera pàgina d'Aurora Libros servida des d'un contenidor.
Docker: De Principiant a Avançat
Mòdul 1: Introducció a Docker
- Què és Docker?
- Instal·lant Docker
- Arquitectura de Docker
- Comandes Bàsiques de Docker
- Entenent les Imatges de Docker
- Creant el teu Primer Contenidor Docker
- El Projecte del Curs: la Plataforma Aurora Libros
Mòdul 2: Treballant amb Imatges Docker
- Docker Hub i Repositoris
- Construint Imatges Docker
- Conceptes Bàsics de Dockerfile
- Instruccions Avançades del Dockerfile
- Gestionant Imatges Docker
- Etiquetatge i Publicació d'Imatges
Mòdul 3: Contenidors Docker
- Executant Contenidors
- Cicle de Vida del Contenidor
- Gestionant Contenidors
- Inspecció i Depuració de Contenidors
- Xarxes a Docker
- Persistència de Dades amb Volums
- Límits de Recursos i Polítiques de Reinici
Mòdul 4: Docker Compose
- Introducció a Docker Compose
- Definint Serveis a Docker Compose
- Comandes de Docker Compose
- Aplicacions Multi-Contenidor
- Variables d'Entorn a Docker Compose
- Perfils, Overrides i Múltiples Entorns
- Desenvolupament Local amb Docker Compose
Mòdul 5: Conceptes Avançats de Docker
- Aprofundiment en Xarxes Docker
- Opcions d'Emmagatzematge Docker
- Millors Pràctiques de Seguretat a Docker
- Optimitzant Imatges Docker
- Builds Avançades amb BuildKit i Buildx
- Registre i Monitoratge a Docker
- El Runtime per Dins: Namespaces, Cgroups i Capes
Mòdul 6: Docker en Producció
- Preparar una Imatge per a Producció
- CI/CD amb Docker
- Orquestrant Contenidors amb Docker Swarm
- Introducció a Kubernetes
- Desplegant Contenidors Docker a Kubernetes
- Escalat i Balanceig de Càrrega
- Estratègies de Desplegament i Rollback
