Tens una imatge professional a la teva màquina: auroralibros/aurora-api:1.1.0, amb usuari sense privilegis, etiquetes OCI, healthcheck i una aturada neta en 0,3 segons. I saps mantenir el magatzem on viu. Li falta l'única cosa que justificava tot el mòdul: sortir del teu portàtil. Una imatge que només existeix a la màquina on es va construir no resol el problema d'Aurora Libros; resol el teu problema local, que no és el mateix. Aquesta lliçó tanca el cicle. Entendràs què fa exactament docker image tag —que no és copiar—, decidiràs una estratègia d'etiquetatge que no t'exploti d'aquí a sis mesos, publicaràs a Docker Hub i també a GitHub Container Registry, i aprendràs per què en producció es desplega per etiqueta immutable o per digest i mai, mai de la vida, per latest. En acabar, qualsevol persona del món amb Docker instal·lat podrà executar l'API d'Aurora Libros amb una sola comanda.
Contingut
docker image tag: referències, no còpies- El nom complet i el registre implícit
- Estratègia d'etiquetatge
latesti per què no s'hi desplega- Publicar a Docker Hub amb
docker push - Verificar el que s'ha publicat
- Publicar a GitHub Container Registry
- Repositoris privats i accés d'equip
- Esborrar etiquetes i per què trenca desplegaments
- Convencions de nomenclatura per a Aurora Libros
docker image tag: referències, no còpies
docker image tag: referències, no còpiesComencem desfent el malentès més estès. docker image tag no copia una imatge, no duplica capes i no ocupa espai addicional. Crea un nom nou que apunta a la mateixa imatge.
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:1.1
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:1
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:latest
docker image ls auroralibros/aurora-api --format "table {{.Tag}}\t{{.ID}}\t{{.Size}}"TAG IMAGE ID SIZE
1 4e9c7d2a8f31 167MB
1.1 4e9c7d2a8f31 167MB
1.1.0 4e9c7d2a8f31 167MB
latest 4e9c7d2a8f31 167MBQuatre files, un sol IMAGE ID. Són quatre noms de la mateixa imatge. I el disc ho confirma:
Abans de crear les tres etiquetes eren 842,3 MB; després, exactament els mateixos 842,3 MB. És la mateixa demostració que vas fer a l'exercici 2 de la lliçó anterior, i el mateix model de l'apartat 1 de la 02-01: les etiquetes són punters a digests, no contenidors de dades.
La sintaxi:
L'origen pot ser un nom existent o un IMAGE ID:
docker image tag 4e9c7d2a8f31 auroralibros/aurora-api:candidata
docker image tag auroralibros/aurora-api:1.1.0 ghcr.io/auroralibros/aurora-api:1.1.0
docker image tag auroralibros/aurora-api:1.1.0 registre.intern.auroralibros.example/aurora-api:1.1.0Les tres són gratuïtes i instantànies. La conseqüència pràctica és important: pots publicar la mateixa imatge en diversos registres sense reconstruir-la. Ho faràs a l'apartat 7.
Regles dels noms d'etiqueta:
| Regla | Vàlid | No vàlid |
|---|---|---|
| Fins a 128 caràcters | 1.1.0-rc.1 |
Una cadena de 200 caràcters |
Lletres, dígits, _, ., - |
v1.1.0, main_2026-08-04 |
1.1.0/rc, versió-1 |
No pot començar per . ni - |
1.1.0 |
.oculta, -beta |
| Majúscules permeses a l'etiqueta | 1.1.0-RC1 |
— |
| El nom del repositori va en minúscules | aurora-api |
Aurora-API |
L'última fila causa errors reals: docker push AuroraLibros/Aurora-API falla amb invalid reference format: repository name must be lowercase.
- El nom complet i el registre implícit
Ja ho vas veure a la lliçó 02-01, però ara és quan importa de debò, perquè el nom determina on va el push:
Docker expandeix aquest nom a docker.io/auroralibros/aurora-api:1.1.0 i envia la imatge a Docker Hub. No hi ha cap opció --registry: si vols publicar en un altre lloc, canvies el nom.
| Nom | Destinació del push |
|---|---|
aurora-api:1.1.0 |
docker.io/library/aurora-api → falla: ningú no pot escriure a library/ |
auroralibros/aurora-api:1.1.0 |
Docker Hub, espai auroralibros |
ghcr.io/auroralibros/aurora-api:1.1.0 |
GitHub Container Registry |
localhost:5000/aurora-api:1.1.0 |
El teu registre local de la lliçó 02-01 |
123456789012.dkr.ecr.eu-west-1.amazonaws.com/aurora-api:1.1.0 |
Amazon ECR |
La primera fila és l'error denied: requested access to the resource is denied que vas diagnosticar a l'exercici 3 de la lliçó 02-01. Ara ja saps que gairebé mai no és un problema de credencials: és un nom sense espai de noms.
Docker distingeix el registre de l'usuari amb una heurística senzilla: si el primer segment conté un punt o dos punts, o és exactament localhost, el tracta com a nom de servidor. Per això ghcr.io/… és un registre i auroralibros/… és un usuari de Docker Hub.
- Estratègia d'etiquetatge
Aquí hi ha la decisió que més problemes evita a mitjà termini. Etiquetar malament no trenca res avui; ho trenca tot d'aquí a sis mesos, quan ningú no sàpiga quina versió hi ha en producció.
Versionatge semàntic: etiquetes fixes i mòbils
El versionatge semàntic (MAJOR.MENOR.PEDAÇ) dona tres números amb significat:
| Component | Quan puja | Exemple a Aurora Libros |
|---|---|---|
| MAJOR | Canvi incompatible a l'API | /llibres canvia el format de resposta |
| MENOR | Funcionalitat nova compatible | S'afegeix /llibres/cercar |
| PEDAÇ | Correcció compatible | S'arregla el càlcul del preu amb IVA |
I d'aquí neixen dues classes d'etiqueta que cal distingir amb claredat:
| Classe | Exemples | Canvia a quina imatge apunta? | Per a què serveix |
|---|---|---|---|
| Fixa (immutable) | 1.1.0, 1.1.0-rc.1, sha-7a3f912 |
Mai | Desplegar, reproduir, auditar |
| Mòbil | 1.1, 1, latest, estable |
Sí, amb cada publicació | Comoditat, seguir una sèrie |
Publicar una versió típica d'Aurora Libros:
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:1.1
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:1
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:latestAmb això, qui consumeix la imatge tria el seu nivell de risc:
flowchart LR
subgraph HOY["Publicació d'1.1.0"]
T1["1.1.0"] --> IMG1["sha256:4e9c…"]
T2["1.1"] --> IMG1
T3["1"] --> IMG1
T4["latest"] --> IMG1
end
subgraph MANANA["Publicació d'1.1.1 (pedaç)"]
U1["1.1.0"] --> IMG1b["sha256:4e9c…<br/>INTACTA"]
U2["1.1.1"] --> IMG2["sha256:8b3f…"]
U3["1.1"] --> IMG2
U4["1"] --> IMG2
U5["latest"] --> IMG2
end
HOY --> MANANA
Fixa't en l'essencial del diagrama: en publicar 1.1.1, l'etiqueta 1.1.0 continua apuntant exactament a la mateixa imatge de sempre. Les mòbils s'han desplaçat. Qui va desplegar 1.1.0 no es veu afectat per res; qui fa servir 1.1 rep el pedaç automàticament.
Altres estratègies
| Estratègia | Exemple | Avantatges | Inconvenients |
|---|---|---|---|
| SemVer fix | 1.1.0 |
Traçable, reproduïble, és l'estàndard | Cal decidir el número a cada release |
| SemVer mòbil | 1.1, 1 |
Pedaços automàtics sense tocar el desplegament | No saps quina imatge exacta corre |
| SHA de commit | sha-7a3f912 |
Traçabilitat perfecta al codi; automàtica a CI | Il·legible per a humans |
| Per branca | main, develop, feature-cercar |
Còmoda en desenvolupament | Mòbil per definició; mai en producció |
| Per entorn | produccio, staging |
Simple d'entendre | Antipatró: amaga quina versió hi ha desplegada |
| Per data | 2026-08-04, 20260804-1142 |
Ordre cronològic obvi | No diu res del contingut |
latest |
latest |
Comoditat en provar | Mai en producció (apartat 4) |
L'estratègia per entorn mereix una advertència especial, perquè sembla raonable i és un parany. Si desplegues auroralibros/aurora-api:produccio, la pregunta "quina versió hi ha en producció?" no té resposta: l'etiqueta s'ha mogut vint vegades i ningú no sap on apunta avui. I un rollback és impossible, perquè la imatge anterior va perdre el nom. El correcte és a l'inrevés: la imatge s'etiqueta per versió, i quina versió va a cada entorn ho decideix el fitxer de desplegament, versionat a Git.
La combinació recomanada
A la pràctica, un pipeline madur publica diverses etiquetes de la mateixa imatge a cada release:
VERSION=1.1.0
COMMIT=$(git rev-parse --short HEAD)
IMATGE=auroralibros/aurora-api
docker build -t $IMATGE:$VERSION \
-t $IMATGE:sha-$COMMIT \
-t $IMATGE:1.1 \
-t $IMATGE:1 \
-t $IMATGE:latest \
--build-arg VERSION=$VERSION \
--build-arg REVISION=$COMMIT \
--build-arg CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)" .Recorda de la lliçó 02-02 que -t és repetible: una sola build, cinc noms, cap cost addicional. Els --build-arg alimenten les etiquetes OCI de la lliçó 02-04, de manera que la imatge porta a dins la mateixa informació que declara a fora. Aquesta coherència és el que permet respondre "quin codi porta això?" amb un sol docker inspect.
latest i per què no s'hi desplega
latest i per què no s'hi desplegalatest no té cap significat especial per a Docker. No és "la més recent", no s'actualitza sola i no la calcula ningú: és simplement l'etiqueta que es fa servir per defecte quan no n'escrius cap. Si ningú no publica una etiqueta anomenada latest, no existeix.
Els problemes de desplegar-hi:
- No és reproduïble.
docker run auroralibros/aurora-api:latestavui i demà poden executar codi diferent. Si demà falla, no pots reproduir l'estat d'avui. - Trenca els rollbacks. "Torna a la versió anterior" no té sentit si l'única referència és
latest. - Pot mentir. Si publiques
1.2.0i després un pedaç1.1.1de la branca antiga sense cura,latestpot acabar apuntant a la versió més vella. És una etiqueta manual, no un càlcul. - Provoca desplegaments heterogenis. Cinc rèpliques arrencades en moments diferents amb
latestpoden estar executant tres versions diferents alhora. - Impedeix auditar. Quin codi hi ha en producció? "Latest." No és una resposta.
La regla d'or: en producció es desplega per etiqueta immutable o per digest. Mai per latest, ni per cap etiqueta mòbil.
Desplegar per digest
El nivell màxim de garantia és referenciar el digest del manifest:
docker pull auroralibros/aurora-api:1.1.0
docker image ls --digests auroralibros/aurora-api --format "{{.Tag}}\t{{.Digest}}"I es desplega així:
docker pull auroralibros/aurora-api@sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3
docker run -d --name aurora-api \
auroralibros/aurora-api@sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3Comparació de garanties:
| Referència | Reproduïble? | Llegible | Ús |
|---|---|---|---|
:latest |
No | Sí | Proves ràpides i res més |
:1.1 |
No (es mou amb els pedaços) | Sí | Desenvolupament |
:1.1.0 |
Sí per conveni (res no impedeix reescriure-la) | Sí | Producció normal |
@sha256:c4f8… |
Sí, criptogràficament | No | Producció crítica, cadena de subministrament auditada |
La fila d'1.1.0 té un matís que convé entendre: res a Docker no impedeix que algú torni a publicar 1.1.0 apuntant a una altra imatge. És una convenció d'equip, no una garantia tècnica. El digest sí que ho és: sha256:c4f8… és el hash del manifest, i si el contingut canviés, el hash seria un altre. Per això els sistemes de desplegament seriosos (Kubernetes en entorns regulats, lliçó 06-05) referencien per digest.
Pots obtenir el digest d'una imatge publicada sense descarregar-la:
- Publicar a Docker Hub amb
docker push
docker pushMoment de la veritat. Recorda de l'apartat 10 de la lliçó 02-01 que el repositori triat és auroralibros/aurora-api, públic.
Pas 1: autenticar-se
Al camp de contrasenya hi enganxes el token d'accés personal amb permís Read & Write, no la teva contrasenya, per tot l'explicat a la lliçó 02-01.
Pas 2: comprovar que el nom és correcte
Si el teu Docker ID real no és auroralibros, reetiqueta abans:
Pas 3: auditar abans de publicar
Aquest pas no és opcional. Una imatge pública és codi publicat, i un cop pujada no hi ha marxa enrere real: algú pot haver-la descarregat el minut següent.
# a) Hi ha algun secret a les variables d'entorn?
docker image inspect auroralibros/aurora-api:1.1.0 --format '{{range .Config.Env}}{{println .}}{{end}}'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NODE_VERSION=22.14.0
YARN_VERSION=1.22.22
NODE_ENV=production
PORT=3000
APP_VERSION=1.1.0Cap credencial. Correcte.
# b) Hi ha algun --build-arg amb secrets a l'historial?
docker image history auroralibros/aurora-api:1.1.0 --no-trunc --format "{{.CreatedBy}}" | grep -iE "password|secret|token|key" || echo "Sense secrets a l'historial"# c) S'hi ha colat algun fitxer que no tocava?
docker run --rm --entrypoint ls auroralibros/aurora-api:1.1.0 -la /appdrwxr-xr-x 1 node node 4096 Aug 4 11:42 .
-rw-r--r-- 1 node node 412 Aug 4 09:15 Dockerfile
drwxr-xr-x 112 node node 4096 Aug 4 11:42 node_modules
-rw-r--r-- 1 node node 44231 Aug 4 09:15 package-lock.json
-rw-r--r-- 1 node node 412 Aug 4 09:15 package.json
-rw-r--r-- 1 node node 6104 Aug 4 11:20 server.jsSense .env, sense .git, sense notes locals. El .dockerignore de la lliçó 02-02 ha fet la seva feina. (Hi apareix el Dockerfile si l'has tret de la llista d'exclusions; no és un problema de seguretat, però convé mantenir-lo exclòs pel que s'hi va explicar.)
Pas 4: el push
The push refers to repository [docker.io/auroralibros/aurora-api]
9c1e4a7f2b9d: Pushed
7d3c9f2e8a51: Pushed
2f8e1a9c4b73: Pushed
b8f4e2a91c37: Mounted from library/node
4a1b8c2f9e3d: Mounted from library/node
8f3e1d7c5b9a: Mounted from library/node
e5c2a8f14b76: Mounted from library/node
1.1.0: digest: sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3 size: 1785Aquesta sortida explica una història, i val la pena llegir-la amb calma:
| Línia | Què significa |
|---|---|
Pushed |
Capa pujada de debò. Són les tres teves: els dos COPY i el RUN npm ci |
Mounted from library/node |
Capa que ja era al registre (pertany a node:22-alpine) i s'ha referenciat, no transferit |
1.1.0: digest: sha256:… |
El digest del manifest, el teu identificador immutable |
size: 1785 |
La mida del manifest en bytes, no la de la imatge |
Les quatre línies Mounted from són l'eficiència de les capes compartides de la lliçó 01-05 portada al registre: dels 167 MB de la imatge, només n'has pujat uns 25. La resta ja vivia allà perquè forma part de la imatge oficial de Node. Per això una imatge ben construïda sobre una base comuna es publica en segons.
Ara les etiquetes restants:
docker push auroralibros/aurora-api:1.1
docker push auroralibros/aurora-api:1
docker push auroralibros/aurora-api:latestThe push refers to repository [docker.io/auroralibros/aurora-api]
9c1e4a7f2b9d: Layer already exists
7d3c9f2e8a51: Layer already exists
2f8e1a9c4b73: Layer already exists
b8f4e2a91c37: Layer already exists
...
1.1: digest: sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3 size: 1785Totes Layer already exists, i el mateix digest que 1.1.0. És la confirmació que les etiquetes són punters: no s'han pujat dades, només s'han creat tres noms nous al registre. Les tres publicacions triguen menys d'un segon entre totes tres.
Una drecera que convé conèixer i fer servir amb cura:
Puja totes les etiquetes locals d'aquell repositori. Còmode, però perillós: si tens una etiqueta local de proves (experiment, depuracio), acabarà publicada. Millor empènyer explícitament el que vols publicar.
- Verificar el que s'ha publicat
No donis mai per bona una publicació sense comprovar-la.
Al web
Entra a https://hub.docker.com/r/auroralibros/aurora-api i ves a la pestanya Tags. Hi hauries de veure 1.1.0, 1.1, 1 i latest, totes amb la mateixa mida comprimida i la mateixa data. És la mateixa pestanya que vas aprendre a llegir a la lliçó 02-01, ara des de l'altre costat.
Amb docker manifest inspect
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 3421,
"digest": "sha256:4e9c7d2a8f31b5c9e2f7a1d4c8b3e6f9a2d5c8b1e4f7a3d6c9b2e5f8a1d4c7b0"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 3622890,
"digest": "sha256:e5c2a8f14b76..."
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 24718432,
"digest": "sha256:2f8e1a9c4b73..."
}
]
}Aquesta comanda consulta el registre remot, no el teu magatzem local: és la prova definitiva que la imatge és allà. El que et diu:
mediaType: el format del manifest (OCI, l'estàndard de la lliçó 01-03).config.digest: l'identificador de la configuració de la imatge.layers: cada capa amb la seva mida comprimida i el seu digest. Allà es veu que la capa delnpm cisón 24,7 MB, coincidint amb el que reportavadocker image historya la lliçó 02-05.
Verifica també que dues etiquetes apunten al mateix:
docker manifest inspect auroralibros/aurora-api:1.1.0 | sha256sum
docker manifest inspect auroralibros/aurora-api:latest | sha256sumb8e2f4a91c37d5e8a2f6c9b1d4e7a3f8c5b2e9d6a1f4c7b0e3a6d9f2c5b8e1a4 -
b8e2f4a91c37d5e8a2f6c9b1d4e7a3f8c5b2e9d6a1f4c7b0e3a6d9f2c5b8e1a4 -Manifests idèntics: 1.1.0 i latest són la mateixa imatge.
La prova real: executar-la des de zero
Aquesta és la que tanca el mòdul. Esborra la imatge local i descarrega-la del registre com faria qualsevol persona del món:
docker image rm auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:1.1 \
auroralibros/aurora-api:1 auroralibros/aurora-api:latest
docker image ls auroralibros/aurora-apiBuit. Ara, des del registre:
Unable to find image 'auroralibros/aurora-api:1.1.0' locally
1.1.0: Pulling from auroralibros/aurora-api
e5c2a8f14b76: Pull complete
2f8e1a9c4b73: Pull complete
...
Status: Downloaded newer image for auroralibros/aurora-api:1.1.0
a7f3c9e2b8d1...curl -s http://localhost:3000/salut
docker ps --filter name=aurora-publicada --format "{{.Names}}: {{.Status}}"{"servei":"aurora-api","version":"1.0.0","db":"ko","cache":"ko",
"errorDb":"connect ECONNREFUSED 127.0.0.1:5432","errorCache":"connect ECONNREFUSED 127.0.0.1:6379"}L'API d'Aurora Libros s'està executant des d'una imatge descarregada d'Internet. Aquell docker run funciona ara mateix en qualsevol màquina del planeta amb Docker instal·lat: sense instal·lar Node, sense nvm, sense npm install, sense conèixer el projecte. Compara-ho amb els set intents i l'hora i mitja de la lliçó 01-07.
- Publicar a GitHub Container Registry
Publicar en un segon registre és habitual: redundància, proximitat al codi, límits de descàrrega diferents. I amb el que saps, costa tres comandes.
Pas 1: crear un token de GitHub
A GitHub: Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token, amb aquests permisos:
| Permís | Per a què |
|---|---|
write:packages |
Publicar imatges |
read:packages |
Descarregar-les |
delete:packages |
Esborrar versions (apartat 9) |
Copia'l: no es torna a mostrar.
Pas 2: autenticar-se
--password-stdin pel que s'ha explicat a la lliçó 02-01: res de contrasenyes a l'historial de l'intèrpret d'ordres. I fixa't que ara tens dues sessions obertes alhora, Docker Hub i ghcr.io, sense que cap interfereixi amb l'altra. La destinació la decideix el nom de la imatge, no un estat global.
Dues entrades, totes dues buides perquè el credential helper desa les credencials al clauer del sistema.
Pas 3: reetiquetar i publicar
docker pull auroralibros/aurora-api:1.1.0 # Si la vas esborrar a l'apartat 6
docker image tag auroralibros/aurora-api:1.1.0 ghcr.io/auroralibros/aurora-api:1.1.0
docker image tag auroralibros/aurora-api:1.1.0 ghcr.io/auroralibros/aurora-api:latest
docker push ghcr.io/auroralibros/aurora-api:1.1.0
docker push ghcr.io/auroralibros/aurora-api:latestThe push refers to repository [ghcr.io/auroralibros/aurora-api]
9c1e4a7f2b9d: Pushed
7d3c9f2e8a51: Pushed
2f8e1a9c4b73: Pushed
b8f4e2a91c37: Pushed
4a1b8c2f9e3d: Pushed
8f3e1d7c5b9a: Pushed
e5c2a8f14b76: Pushed
1.1.0: digest: sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3 size: 1785Dues observacions importants:
- Totes les capes diuen
Pushed, capMounted from. És lògic: aghcr.iono hi havia cap còpia prèvia de les capes denode:22-alpine, així que s'han pujat senceres. La primera publicació en un registre nou sempre és la lenta. - El digest és idèntic al de Docker Hub:
sha256:c4f81b2e…. La imatge és exactament la mateixa als dos registres, bit a bit. El digest depèn del contingut, no d'on estigui allotjat.
A GitHub, el paquet apareix a https://github.com/users/auroralibros/packages. Un detall: per defecte els paquets de ghcr.io són privats. Per fer-lo públic cal anar a Package settings → Change visibility → Public. I per enllaçar-lo amb el repositori de codi, n'hi ha prou que l'etiqueta OCI org.opencontainers.image.source de la lliçó 02-04 apunti al repositori: GitHub la llegeix i connecta tots dos automàticament. Aquella feina de metadades comença a rendir aquí.
Comparativa dels dos registres per a Aurora Libros:
| Aspecte | Docker Hub | GitHub Container Registry |
|---|---|---|
| Repositoris privats al pla gratuït | Quota limitada | Il·limitats |
| Límit de descàrregues anònimes | Sí (lliçó 02-01) | Molt més laxe |
| Integració amb el codi | Manual | Automàtica via l'etiqueta OCI source |
| Descobribilitat pública | Màxima | Menor |
| Permisos | Per organització | Heretats del repositori de GitHub |
Per a Aurora Libros, la política raonable: Docker Hub com a registre públic (descobrible, és on la gent busca) i ghcr.io com a registre de treball de l'equip, integrat amb el codi i amb privats sense cost.
- Repositoris privats i accés d'equip
Aurora Libros és una empresa: la seva API real no hauria de ser pública. Així es canvia.
Fer privat un repositori a Docker Hub
- Entra al repositori → pestanya Settings.
- Visibility settings → Make private.
- Confirma escrivint el nom del repositori.
L'efecte és immediat:
Error response from daemon: pull access denied for auroralibros/aurora-api,
repository does not exist or may require 'docker login': denied: requested access
to the resource is deniedÉs el missatge ambigu de l'exercici 3 de la lliçó 02-01, ara amb la causa que faltava en aquella llista: el repositori existeix, però sense sessió no ho pots ni saber. El registre no distingeix entre "no existeix" i "no tens permís" a propòsit, per no filtrar quins repositoris privats té una organització.
Donar accés a un equip
Un repositori privat sota un compte personal només el veu el seu propietari. Per a un equip cal una organització:
- Docker Hub → Organizations → Create Organization (per exemple,
auroralibros). - A dins, Teams → crear equips per funció:
| Equip | Permís | Qui |
|---|---|---|
desenvolupament |
Read | Desenvolupadors: descarreguen per treballar en local |
ci |
Read & Write | El compte de servei del pipeline: construeix i publica |
plataforma |
Admin | Responsables: visibilitat, esborrats, configuració |
- Afegir membres a cada equip.
- Al repositori → Permissions → assignar cada equip al seu nivell.
Dos principis que cal respectar:
- Mínim privilegi. Una desenvolupadora no necessita
write. Si ningú més que el pipeline no publica, ningú més que el pipeline no ho ha de poder fer. - Comptes de servei per a l'automatització. El pipeline no fa servir mai les credencials personals de ningú: fa servir un compte propi amb un token de permisos limitats. Si aquella persona marxa de l'empresa, el pipeline no cau.
A GitHub Container Registry és més senzill perquè hereta del repositori de codi: qui té accés de lectura al repo té accés al paquet, i s'ajusta a Package settings → Manage Actions access.
- Esborrar etiquetes i per què trenca desplegaments
Es pot esborrar una etiqueta publicada. Gairebé mai no s'ha de fer.
A Docker Hub: repositori → pestanya Tags → seleccionar → Delete. Per esborrar el repositori sencer, Settings → Delete repository.
A ghcr.io: pàgina del paquet → Package settings → Manage versions → Delete.
Per què és perillós
Una etiqueta publicada és una dependència d'altres. Pensa en el que passa en esborrar auroralibros/aurora-api:1.1.0:
- Els desplegaments existents fallen en reiniciar-se. Els contenidors en marxa continuen vius (tenen la imatge en local), però qualsevol màquina nova, qualsevol rèplica que escali i qualsevol reinici després d'un
docker system prunedona:
Error response from daemon: manifest for auroralibros/aurora-api:1.1.0 not found:
manifest unknown: manifest unknown- Els rollbacks esdevenen impossibles. La versió anterior era exactament el que necessitaves per tornar enrere.
- Els pipelines es trenquen. Qualsevol Dockerfile que fes
FROM auroralibros/aurora-api:1.1.0deixa de construir. - La traçabilitat desapareix. No es pot reproduir un incident de fa tres mesos.
I una variant encara pitjor: reescriure una etiqueta publicada, és a dir, fer push d'una imatge diferent amb el mateix 1.1.0. Ningú no se n'assabenta, les màquines que ja la tenen continuen amb la vella, les noves descarreguen la nova, i acabes amb un desplegament on 1.1.0 significa dues coses diferents segons quan va arrencar cada rèplica. És una de les incidències més difícils de diagnosticar que existeixen.
Quan sí que cal esborrar
| Situació | Acció |
|---|---|
| S'ha publicat un secret per error | Esborrar immediatament i, sobretot, rotar la credencial: cal assumir que ja està compromesa |
Etiquetes de desenvolupament antigues (pr-142, sha-… de fa mesos) |
Esborrat rutinari, amb polítiques de retenció |
| Versió amb una fallada greu de seguretat | Millor publicar 1.1.1 corregida i marcar l'anterior com a obsoleta a la descripció, que esborrar-la |
| Versió estable en ús | Mai |
L'alternativa correcta a l'esborrat és la deprecació: publicar una versió nova, documentar a la descripció del repositori que l'anterior no s'ha de fer servir i donar un termini. S'avisa, no es trenca.
I una advertència sobre els secrets: esborrar l'etiqueta no esborra el problema. Si vas publicar una contrasenya dins d'una imatge, qualsevol la va poder descarregar durant els minuts que va estar disponible. L'única resposta vàlida és rotar aquella credencial. Per això el pas 3 de l'apartat 5 —auditar abans de publicar— no és burocràcia.
- Convencions de nomenclatura per a Aurora Libros
Tanquem amb la decisió escrita, que és el que un equip real acorda i documenta al seu repositori.
Repositoris
Un repositori per artefacte desplegable, mai un per projecte:
| Servei | Repositori | Registre públic | Registre d'equip |
|---|---|---|---|
| API del catàleg | aurora-api |
docker.io/auroralibros/aurora-api |
ghcr.io/auroralibros/aurora-api |
| Web i proxy | aurora-web |
docker.io/auroralibros/aurora-web |
ghcr.io/auroralibros/aurora-web |
| Base de dades | (no escau) | Es fa servir postgres:16-alpine oficial |
— |
| Memòria cau | (no escau) | Es fa servir redis:7-alpine oficial |
— |
Les dues últimes files són una decisió deliberada: no es reempaqueten imatges oficials sense motiu. aurora-db farà servir postgres:16-alpine tal qual, amb la seva inicialització muntada des de fora (mòdul 3). Crear una imatge pròpia només per ficar-hi dins un init.sql afegeix una imatge per mantenir a canvi de res.
Etiquetes
| Etiqueta | Quan es publica | Mòbil? | Ús permès |
|---|---|---|---|
1.1.0 |
A cada release, des d'una etiqueta de Git | No | Producció |
1.1 |
Amb cada pedaç de la sèrie 1.1 | Sí | Desenvolupament, entorns de prova |
1 |
Amb cada versió menor de la sèrie 1 | Sí | Desenvolupament |
latest |
Amb l'última versió estable | Sí | Proves ràpides. Mai en producció |
sha-7a3f912 |
A cada commit de main, des de CI |
No | Depuració, traçabilitat, rollback fi |
1.2.0-rc.1 |
Candidates a versió | No | Entorn de preproducció |
pr-142 |
A cada pull request | Sí | Revisió; s'esborra en tancar la PR |
Regles acordades
- Producció es desplega per etiqueta immutable (
1.1.0) o per digest. Mai perlatest,1.1ni1. - Una etiqueta fixa publicada no es reescriu mai. Si hi ha una fallada, es publica una versió nova.
- Tota imatge porta les etiquetes OCI de la lliçó 02-04, amb
versionirevisioncoincidint amb les etiquetes del registre. - Només el compte de servei de CI publica en producció. Les persones publiquen, com a molt, etiquetes
pr-*isha-*. - Auditar abans de publicar: variables d'entorn, historial i contingut d'
/app. - Les etiquetes
pr-*caduquen als 30 dies, amb política de retenció automàtica.
Un exemple de la comanda completa de release, que és el que executarà el pipeline de la lliçó 06-02:
#!/bin/bash
# publicar-release.sh — publica una versió d'aurora-api als dos registres
set -euo pipefail
VERSION="${1:?Ús: publicar-release.sh <versio> ex: 1.1.0}"
COMMIT=$(git rev-parse --short HEAD)
CREATED=$(date -u +%Y-%m-%dT%H:%M:%SZ)
MAJOR="${VERSION%%.*}"
MENOR="${VERSION%.*}"
for REG in "auroralibros" "ghcr.io/auroralibros"; do
IMG="$REG/aurora-api"
docker build \
-t "$IMG:$VERSION" \
-t "$IMG:$MENOR" \
-t "$IMG:$MAJOR" \
-t "$IMG:latest" \
-t "$IMG:sha-$COMMIT" \
--build-arg VERSION="$VERSION" \
--build-arg REVISION="$COMMIT" \
--build-arg CREATED="$CREATED" \
--pull \
./api
for T in "$VERSION" "$MENOR" "$MAJOR" "latest" "sha-$COMMIT"; do
docker push "$IMG:$T"
done
done
echo "Publicada $VERSION (commit $COMMIT) a Docker Hub i ghcr.io"
docker manifest inspect "auroralibros/aurora-api:$VERSION" --verbose | grep -m1 digestFixa't en els detalls: set -euo pipefail avorta davant de qualsevol error, ${VERSION%%.*} i ${VERSION%.*} deriven 1 i 1.1 d'1.1.0 amb expansió de paràmetres de l'intèrpret d'ordres, --pull garanteix la base actualitzada com es va explicar a 02-02, i els --build-arg mantenen coherents les etiquetes OCI internes amb les del registre.
Errors Habituals i Consells
- Creure que
docker image tagcopia la imatge. Crea una referència; el disc no creix. Quatre etiquetes de la mateixa imatge ocupen el que una. docker push aurora-api:1.1.0sense espai de noms. S'expandeix alibrary/aurora-apii falla ambdenied. Davant d'undenieden un push, mira el nom abans que les credencials.- Majúscules al nom del repositori.
invalid reference format: repository name must be lowercase. Només l'etiqueta admet majúscules. - Desplegar amb
latest. No és reproduïble, impedeix el rollback, pot apuntar a una versió més antiga i fa impossible auditar què hi ha en producció. - Etiquetar per entorn (
produccio,staging). Antipatró: l'etiqueta es mou i ningú no sap quina versió corre. Etiqueta per versió i decideix al desplegament. - Reescriure una etiqueta fixa ja publicada. Provoca desplegaments on
1.1.0significa coses diferents segons quan va arrencar cada rèplica. Publica una versió nova. - Esborrar una etiqueta publicada. Trenca reinicis, escalats i rollbacks de tothom qui la faci servir. Depreca en lloc d'esborrar.
- Publicar sense auditar. Un secret publicat s'ha de donar per compromès: esborrar l'etiqueta no n'hi ha prou, cal rotar la credencial.
docker push --all-tagsa la lleugera. Publica també les teves etiquetes de proves locals.- Fer servir la contrasenya en lloc d'un token. Un token es revoca sense canviar la contrasenya, té permisos limitats i en pots tenir un per màquina.
- Consell: verifica sempre amb
docker manifest inspect. Consulta el registre remot, no la teva memòria cau local: és l'única prova real que la publicació va funcionar. - Consell: esborra la imatge local i descarrega-la del registre abans de donar per bona una release. És l'única manera de comprovar que el que has publicat és autosuficient.
- Consell: fes que les etiquetes OCI internes coincideixin amb les del registre. Que
org.opencontainers.image.versiondigui1.1.0i l'etiqueta sigui1.1.0t'estalviarà més d'una investigació.
Exercicis
Exercici 1: demostra que les etiquetes són punters
- Anota el resultat de
docker system df(línia d'Images). - Crea cinc etiquetes noves per a
auroralibros/aurora-api:1.1.0:1.1,1,latest,estableisha-abc1234. - Torna a executar
docker system df. Ha crescut l'espai? Per què? - Comprova que les sis referències comparteixen IMAGE ID.
- Esborra les etiquetes
estableisha-abc1234. Quin missatge dona cada esborrat? I si esborressis les sis? - Reconstrueix la imatge després de modificar
server.js, etiquetant-la de nou com a1.1.0. Què passa amb1.1,1ilatest? Explica el resultat en termes de punters.
Exercici 2: publica i verifica el cicle complet
Amb el teu compte real de Docker Hub (substitueix auroralibros pel teu Docker ID):
- Audita la imatge abans de publicar: variables d'entorn, historial a la recerca de secrets i contingut d'
/app. - Publica
1.1.0ilatest, i analitza la sortida del primer push: quantes capes diuenPushedi quantesMounted from? Per què? - Analitza la sortida del segon push. Per què és instantani?
- Verifica amb
docker manifest inspectque totes dues etiquetes tenen el mateix digest. - Esborra totes les còpies locals i executa l'API descarregant-la del registre. Comprova
/saluti l'estat del healthcheck. - Obtén el digest i executa la imatge referenciant-la per
@sha256:…en lloc de per etiqueta.
Exercici 3: dissenya l'estratègia d'etiquetatge d'Aurora Libros
L'equip d'Aurora Libros et planteja quatre situacions. Per a cadascuna, indica quines etiquetes publicaries, quina desplegaries en producció i per què:
a) Release estable de la versió 1.2.0, amb una funcionalitat nova (/llibres/cercar) des del commit 9c4e1a7 de la branca main.
b) Correcció urgent d'una fallada de seguretat a la 1.2.0, que cal desplegar en producció avui mateix.
c) Una pull request número 87 que afegeix paginació i cal provar a l'entorn de revisió.
d) Canvi incompatible: /llibres passa a retornar {dades: [...], total: n} en lloc d'un array. Trenca el web actual.
A més, respon:
e) Un company proposa docker push auroralibros/aurora-api:produccio a cada desplegament. Dona tres arguments tècnics concrets per rebutjar-ho i una alternativa.
Solucions
Solució a l'exercici 1
# 2
for T in 1.1 1 latest estable sha-abc1234; do
docker image tag auroralibros/aurora-api:1.1.0 auroralibros/aurora-api:$T
done
# 3
docker system df --format "table {{.Type}}\t{{.TotalCount}}\t{{.Size}}" | head -2Ni el recompte ni la mida han canviat. El recompte continua sent 9 perquè docker system df compta imatges, no referències, i les sis etiquetes són una sola imatge. docker image tag escriu una entrada en un índex de noms; no toca ni un byte de les capes.
TAG IMAGE ID
1 4e9c7d2a8f31
1.1 4e9c7d2a8f31
1.1.0 4e9c7d2a8f31
estable 4e9c7d2a8f31
latest 4e9c7d2a8f31
sha-abc1234 4e9c7d2a8f31Només Untagged, sense Deleted: queden quatre referències apuntant a la imatge, així que les dades continuen sent-hi. Si esborressis les sis, l'última mostraria Untagged i una llista de Deleted: sha256:…, una per capa exclusiva. El Deleted apareix únicament quan cau l'última referència, tal com vas veure a la lliçó 02-05.
# 6
cd ~/aurora-libros/api
echo "// canvi per a l'exercici" >> server.js
docker build -q -t auroralibros/aurora-api:1.1.0 .
docker image ls auroralibros/aurora-api --format "table {{.Tag}}\t{{.ID}}"Només 1.1.0 s'ha mogut a la imatge nova. Les altres tres continuen apuntant a la vella, que ja no és dangling perquè conserva noms. Això demostra que etiquetar és un acte explícit: Docker no propaga res. Si vols que 1.1, 1 i latest segueixin la versió nova, cal reetiquetar-les a mà (o generar totes les etiquetes al mateix docker build amb diversos -t, com a l'script de l'apartat 10).
I compte amb el que acabes de fer sense voler: has reescrit el contingut de l'etiqueta 1.1.0. En local és inofensiu; publicada, seria exactament l'antipatró de l'apartat 9.
Solució a l'exercici 2
# 1. Auditoria prèvia
docker image inspect auroralibros/aurora-api:1.1.0 --format '{{range .Config.Env}}{{println .}}{{end}}'
docker image history auroralibros/aurora-api:1.1.0 --no-trunc --format "{{.CreatedBy}}" \
| grep -iE "password|secret|token|api[_-]?key" || echo "OK: sense secrets"
docker run --rm --entrypoint ls auroralibros/aurora-api:1.1.0 -la /app9c1e4a7f2b9d: Pushed
7d3c9f2e8a51: Pushed
2f8e1a9c4b73: Pushed
b8f4e2a91c37: Mounted from library/node
4a1b8c2f9e3d: Mounted from library/node
8f3e1d7c5b9a: Mounted from library/node
e5c2a8f14b76: Mounted from library/node
1.1.0: digest: sha256:c4f81b2e9a7d... size: 1785Tres Pushed i quatre Mounted from. Les tres pujades són les capes que genera el teu Dockerfile: COPY package*.json, RUN npm ci i COPY . .. Les quatre muntades pertanyen a node:22-alpine, que ja era a Docker Hub: el registre les referencia en lloc de rebre-les. De 167 MB d'imatge se'n transfereixen uns 25. És el mateix estalvi de les capes compartides de la lliçó 01-05, ara a la xarxa.
Instantani perquè no es transfereix res: totes les capes ja són al registre i el manifest és idèntic. L'única cosa que passa és que es crea un nom nou apuntant al mateix digest. Publicar deu etiquetes de la mateixa imatge costa pràcticament el mateix que publicar-ne una.
# 4
docker manifest inspect auroralibros/aurora-api:1.1.0 | sha256sum
docker manifest inspect auroralibros/aurora-api:latest | sha256sumb8e2f4a91c37d5e8a2f6c9b1d4e7a3f8c5b2e9d6a1f4c7b0e3a6d9f2c5b8e1a4 -
b8e2f4a91c37d5e8a2f6c9b1d4e7a3f8c5b2e9d6a1f4c7b0e3a6d9f2c5b8e1a4 -Idèntics.
# 5
docker image rm -f $(docker image ls -q auroralibros/aurora-api)
docker image ls auroralibros/aurora-api
docker run -d --name des-de-registre -p 3000:3000 auroralibros/aurora-api:1.1.0
sleep 45
curl -s http://localhost:3000/salut
docker ps --filter name=des-de-registre --format "{{.Names}}: {{.Status}}"(llistat buit)
Unable to find image 'auroralibros/aurora-api:1.1.0' locally
1.1.0: Pulling from auroralibros/aurora-api
...
{"servei":"aurora-api","version":"1.0.0","db":"ko","cache":"ko",...}
des-de-registre: Up 45 seconds (unhealthy)Funciona des de zero, i el healthcheck de la lliçó 02-04 fa la seva feina: unhealthy perquè no hi ha PostgreSQL ni Redis, exactament l'esperat fins al mòdul 3.
# 6. Per digest
DIGEST=$(docker image ls --digests auroralibros/aurora-api --format "{{.Digest}}" | head -1)
echo "$DIGEST"
docker rm -f des-de-registre
docker run -d --name per-digest -p 3000:3000 "auroralibros/aurora-api@$DIGEST"
docker ps --filter name=per-digest --format "{{.Image}}"sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3
auroralibros/aurora-api@sha256:c4f81b2e9a7d3061f5b8c2e4a9d7f3b1e6c8a2d4f9b7e3c1a5d8f2b6e4c9a7d3Fixa't en la columna IMAGE de docker ps: mostra el digest, no una etiqueta. Aquell contenidor està lligat criptogràficament a un contingut concret, i cap reescriptura d'etiquetes al registre no pot canviar el que executa.
Solució a l'exercici 3
(a) Release estable 1.2.0 des de 9c4e1a7:
docker build -t auroralibros/aurora-api:1.2.0 \
-t auroralibros/aurora-api:1.2 \
-t auroralibros/aurora-api:1 \
-t auroralibros/aurora-api:latest \
-t auroralibros/aurora-api:sha-9c4e1a7 \
--build-arg VERSION=1.2.0 --build-arg REVISION=9c4e1a7 \
--pull ./apiÉs una funcionalitat compatible (afegeix un endpoint sense canviar els existents), així que puja el número MENOR. En producció es desplega 1.2.0, l'etiqueta immutable. Les mòbils 1.2, 1 i latest es publiquen per comoditat de qui desenvolupa, i sha-9c4e1a7 dona traçabilitat exacta al commit.
(b) Correcció urgent de seguretat:
docker build -t auroralibros/aurora-api:1.2.1 \
-t auroralibros/aurora-api:1.2 \
-t auroralibros/aurora-api:1 \
-t auroralibros/aurora-api:latest \
-t auroralibros/aurora-api:sha-4b8f2c1 \
--build-arg VERSION=1.2.1 --build-arg REVISION=4b8f2c1 \
--pull --no-cache ./apiPuja el PEDAÇ: és una correcció compatible. Es desplega 1.2.1. Tres decisions importants:
- No es toca
1.2.0. Continua existint i continua apuntant a la imatge antiga. Això permet un rollback immediat si1.2.1surt malament, i és tota la diferència entre un incident controlat i un que s'agreuja. --no-cache, perquè es tracta d'un pedaç de seguretat i no vols reutilitzar capes que puguin contenir la versió vulnerable d'una dependència.--pull, perquè la basenode:22-alpineporti també els seus pedaços.
Si la vulnerabilitat fos a la mateixa 1.2.0, la resposta correcta no és esborrar aquella etiqueta (trencaria tothom qui la fes servir, inclosos els qui encara no han pogut actualitzar), sinó documentar-la com a obsoleta a la descripció del repositori i comunicar l'actualització.
(c) Pull request 87:
docker build -t auroralibros/aurora-api:pr-87 \
-t auroralibros/aurora-api:sha-e1d7a92 \
--build-arg VERSION=1.2.1-pr87 --build-arg REVISION=e1d7a92 ./apiEtiqueta efímera pr-87, mòbil (se sobreescriu amb cada push a la branca de la PR), i una sha-* immutable per poder reproduir exactament el que s'ha provat. No es publiquen latest, 1.2 ni cap mòbil de la sèrie estable: contaminarien el canal que consumeixen altres. En tancar la PR, pr-87 s'esborra; és un dels pocs esborrats d'etiqueta legítims, perquè ningú no la fa servir en producció per definició.
(d) Canvi incompatible a /llibres:
Puja el número MAJOR, perquè trenca els consumidors existents (el web actual espera un array). I es publica primer com a candidata 2.0.0-rc.1, no com a estable.
A més, latest no es mou encara. Aquest és el matís que més equips obliden: si latest saltés a la 2.0.0, qualsevol que estigués fent servir latest en un entorn de proves veuria com se li trenca el web sense haver canviat res. La seqüència correcta és: publicar la RC, actualitzar aurora-web per consumir el format nou, provar-los tots dos junts, i només aleshores publicar 2.0.0 i moure latest i 2. L'etiqueta 1 continua apuntant a la sèrie 1 per a qui necessiti temps per migrar.
(e) Tres arguments contra :produccio:
- No és reproduïble ni auditable. La pregunta "quin codi hi ha en producció?" deixa de tenir resposta: l'etiqueta s'ha mogut cinquanta vegades i no queda registre d'on apunta avui ni d'on apuntava durant l'incident del dimarts passat.
- Impossibilita el rollback. En moure
:produccioa la versió nova, l'anterior perd la seva única referència. Tornar enrere exigeix saber l'IMAGE ID o el digest antic, i sense un registre escrit d'això, no hi ha marxa enrere. - Provoca desplegaments heterogenis. Amb
imagePullPolicy: Alwayso després d'un reinici, unes rèpliques descarreguen la versió nova i altres conserven la vella: la mateixa etiqueta executant dos codis alhora, amb errors intermitents impossibles de reproduir.
Un quart argument, si cal: acobla la imatge a l'entorn, trencant el principi de "construir una vegada, desplegar a tot arreu". El mateix artefacte ha de servir per a proves i per a producció; el que canvia és la configuració injectada, no la imatge.
L'alternativa: etiquetar per versió (1.2.1) i desar a Git, dins del repositori de desplegament, quina versió correspon a cada entorn:
# desplegament/produccio.yaml
imatge: auroralibros/aurora-api:1.2.1
# desplegament/staging.yaml
imatge: auroralibros/aurora-api:1.3.0-rc.2Així, "què hi ha en producció" es respon amb un git log d'un fitxer, el rollback és revertir un commit, i l'historial complet de desplegaments queda auditat. És exactament el plantejament que es desenvoluparà a la lliçó 06-07, sobre estratègies de desplegament i rollback.
Conclusió
Has tancat el cicle. docker image tag no copia res: crea referències, i quatre etiquetes de la mateixa imatge ocupen exactament el que una, com va confirmar docker system df sense moure's ni un byte. El nom complet registre/usuari/repositori:etiqueta és el que decideix la destinació d'un push —no existeix cap opció --registry—, i per això un denied gairebé sempre és un nom sense espai de noms abans que un problema de credencials. Has distingit les etiquetes fixes de les mòbils, has vist per què etiquetar per entorn és un antipatró que esborra la traçabilitat, i t'endús la regla que més disgustos evita: en producció es desplega per etiqueta immutable o per digest, mai per latest, amb @sha256:… com a única garantia criptogràfica real.
I has publicat. auroralibros/aurora-api:1.1.0 viu a Docker Hub i a GitHub Container Registry, amb el mateix digest a tots dos perquè la imatge és idèntica bit a bit. Saps llegir la sortida d'un push —Pushed per a les teves tres capes, Mounted from library/node per a les quatre que el registre ja tenia, i dels 167 MB només en van viatjar uns 25—, verificar-la contra el registre remot amb docker manifest inspect, fer privat un repositori i repartir permisos per equips amb el principi de mínim privilegi. I saps per què esborrar una etiqueta publicada trenca reinicis, escalats i rollbacks aliens, i per què davant d'un secret filtrat l'única cosa que serveix és rotar la credencial.
Fes balanç del que ha canviat en aquest mòdul. Vas començar amb un repositori de codi, quinze passos manuals d'onboarding i una API que només arrencava en màquines amb Node 22, nvm, PostgreSQL i Redis instal·lats a mà. Acabes amb una imatge publicada que s'executa amb una sola comanda en qualsevol màquina del món amb Docker: sense instal·lar Node, sense npm install, sense conèixer el projecte. Pel camí has entès el context de construcció i l'has retallat de 23,41 MB a 47,83 kB amb un .dockerignore, has domat la memòria cau de capes fins a passar de 46,7 a 1,4 segons per build, has escrit un Dockerfile línia a línia justificant cada decisió, l'has professionalitzat amb usuari sense privilegis, metadades OCI i un healthcheck real contra /salut, i has après a mantenir el teu magatzem d'imatges sense destruir el que importa. Els passos 1 a 5 d'aquella llista de quinze han desaparegut.
Però la teva imatge continua retornant ECONNREFUSED a /llibres, i aquesta fallada fa tres lliçons que t'espera. Dins del contenidor, localhost és el contenidor mateix: no hi ha cap PostgreSQL ni cap Redis allà dins, i per això el healthcheck marca unhealthy amb tota la raó. Al mòdul 3, Contenidors Docker, aquests contenidors deixen de ser demostracions aïllades i comencen a funcionar de debò: dominaràs les opcions de docker run i el cicle de vida complet, aprendràs a inspeccionar i depurar un contenidor per dins, crearàs una xarxa pròpia on aurora-api trobi aurora-db cridant-la pel seu nom, donaràs a PostgreSQL un volum perquè el catàleg de vuit llibres sobrevisqui a la destrucció del contenidor, i posaràs límits de memòria i polítiques de reinici als quatre serveis. En acabar-lo, curl http://localhost:3000/llibres retornarà per fi El jardín de senderos que se bifurcan, Rayuela i els altres sis títols, servits des d'una base de dades real en un contenidor real. La plataforma d'Aurora Libros començarà a estar viva.
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
