A la lliçó 03-06 vas aprendre a fer servir volums, bind mounts i tmpfs. Aquí veuràs què hi ha a sota: com el daemon apila les capes d'una imatge amb overlay2, quant costa de debò escriure a la capa d'un contenidor, què són els volume drivers i com muntar una estratègia de còpies de seguretat d'Aurora Libros amb restauració provada.
Contingut
- Què és un storage driver i què resol
overlay2per dins: els quatre directoris- Inspecció real d'una imatge i d'un contenidor
- Taula comparativa dels storage drivers
- Consultar el driver actiu i canviar-lo
- El cost del copy-on-write, mesurat
- Per què les bases de dades exigeixen volums
- El driver
locali els seusdriver_opts - Muntar NFS i
tmpfscom a volum - Plugins de tercers i declaració a Compose
- Volums
externalcompartits entre piles - Estratègia de còpies de seguretat d'Aurora Libros
- Script de còpia amb rotació i restauració verificada
- Espai al disc i
data-root - Rendiment i permisos (UID/GID)
- Què és un storage driver i què resol
Una imatge és una pila de capes de només lectura (lliçó 01-05). Un contenidor hi afegeix a sobre una capa d'escriptura. El problema tècnic és aquest: presentar totes aquelles capes com un únic sistema de fitxers coherent, i fer-ho sense copiar gigabytes cada vegada que arrenca un contenidor.
D'això se n'encarrega el storage driver del daemon. Té tres responsabilitats:
- Apilar les capes de la imatge en un sol arbre de directoris visible des de dins.
- Aplicar copy-on-write: en modificar un fitxer d'una capa inferior, copiar-lo a la capa superior i treballar sobre la còpia.
- Compartir les capes comunes entre contenidors, perquè deu instàncies de
node:22-alpineocupin l'espai d'una.
És una peça del daemon, no del contenidor: a dins només s'hi veu un sistema de fitxers normal.
overlay2 per dins: els quatre directoris
overlay2 per dins: els quatre directorisoverlay2 fa servir OverlayFS, un sistema de fitxers d'unió inclòs al kernel de Linux. Treballa amb quatre conceptes:
| Directori | Què conté | Mode |
|---|---|---|
lowerdir |
Les capes de la imatge, apilades i separades per : |
Només lectura |
upperdir |
La capa d'escriptura del contenidor | Lectura i escriptura |
merged |
La vista unificada: el que el contenidor veu com a / |
Lectura i escriptura |
workdir |
Espai intern de treball del kernel per a operacions atòmiques | Ús intern |
Les regles de resolució són senzilles i expliquen tot el comportament que ja has observat:
- Llegir un fitxer: es busca a
upperdir; si no hi és, es recorrelowerdirde dalt a baix. Guanya la primera coincidència. - Escriure en un fitxer que només existeix a
lowerdir: es copia sencer aupperdir(copy-up) i s'hi escriu. L'original no es toca. - Esborrar un fitxer de
lowerdir: no es pot esborrar el que és de només lectura, així que es crea aupperdirun fitxer especial de tipus whiteout que l'amaga. L'original continua ocupant espai.
Aquesta tercera regla és la raó, per fi explicada, que esborrar fitxers en una capa posterior d'un Dockerfile no redueixi la mida de la imatge. Ho veurem mesurat a la lliçó 05-04.
flowchart TB M["merged/ ← el que veu el contenidor"] U["upperdir/ capa d'escriptura<br/>fitxers nous, copy-up i whiteouts"] L3["lowerdir 3 · COPY src/ (aurora-api)"] L2["lowerdir 2 · npm ci --omit=dev"] L1["lowerdir 1 · node:22-alpine"] U --> M L3 --> M L2 --> M L1 --> M
- Inspecció real d'una imatge i d'un contenidor
Tot això és visible al disc del host. Cada capa viu a /var/lib/docker/overlay2/<id>/:
docker image inspect auroralibros/aurora-api:1.2.0 --format '{{json .GraphDriver.Data}}' | tr ',' '\n'
mount | grep overlay | head -1 | tr ',' '\n' | grep -E 'lowerdir|upperdir|workdir' | cut -c1-70{"LowerDir":"/var/lib/docker/overlay2/4a8e77/diff:/var/lib/docker/overlay2/c93b2e/diff"
"MergedDir":"/var/lib/docker/overlay2/7d1f0a/merged"
"UpperDir":"/var/lib/docker/overlay2/7d1f0a/diff"
"WorkDir":"/var/lib/docker/overlay2/7d1f0a/work"}
lowerdir=/var/lib/docker/overlay2/l/QW3F:/var/lib/docker/overlay2/l/K7RT
upperdir=/var/lib/docker/overlay2/9be21c/diff
workdir=/var/lib/docker/overlay2/9be21c/workFixa't en els enllaços curts d'overlay2/l/: existeixen perquè la longitud dels arguments de muntatge del kernel està limitada, i una imatge amb moltes capes superaria el límit amb rutes completes.
Ara la demostració que ho tanca tot. Escriu un fitxer dins del contenidor i mira'l aparèixer a l'upperdir del host:
up=$(docker inspect aurora-libros-aurora-api-1 --format '{{.GraphDriver.Data.UpperDir}}')
docker compose exec aurora-api sh -c 'echo "prova de capes" > /tmp/aurora.txt'
sudo cat "$up/tmp/aurora.txt" && sudo find "$up" -type f | head -2El fitxer és físicament al host, dins del diff d'aquell contenidor i només d'aquell contenidor. És el mateix que docker diff mostrava a la lliçó 03-03, però ara saps on viu.
- Taula comparativa dels storage drivers
| Driver | Estat el 2026 | Requisits | Rendiment | Notes |
|---|---|---|---|---|
overlay2 |
Estàndard per defecte | Kernel ≥ 4.0, ext4 o xfs amb ftype=1 |
Molt bo en lectura; copy-up costós en fitxers grans | L'opció correcta llevat de motiu de pes |
btrfs |
Suportat | Sistema de fitxers Btrfs a /var/lib/docker |
Bo; instantànies natives i molt barates | Útil si ja fas servir Btrfs; requereix manteniment |
zfs |
Suportat | ZFS instal·lat | Bo; compressió i snapshots | Consum de RAM alt (ARC); llicència fora del kernel |
devicemapper |
Eliminat | — | Dolent en mode loop-lvm |
Històric; retirat a Docker 25. Si el veus, migra |
fuse-overlayfs |
Suportat | Mode rootless en kernels antics | Pitjor que overlay2: passa per espai d'usuari |
Kernels ≥ 5.13 ja no el necessiten |
vfs |
Últim recurs | Cap | Molt dolent: copia sencera cada capa | Sense CoW; només per a proves o entorns imbricats |
Regla pràctica: si docker info diu overlay2, no toquis res; si diu vfs en un servidor, tens un problema de configuració que multiplicarà per deu l'espai al disc.
- Consultar el driver actiu i canviar-lo
Canviar el driver es fa a /etc/docker/daemon.json amb {"storage-driver": "overlay2"} i reiniciant el daemon.
Advertència. Canviar el storage driver fa que el daemon deixi de veure totes les imatges i contenidors existents: continuen al disc, sota el directori del driver antic, però són inaccessibles fins que tornis enrere. Abans de tocar-ho, publica les teves imatges en un registre d'imatges, desa les que no estiguin publicades amb
docker savei fes còpia de seguretat dels volums. Els volums, això sí, no depenen del driver: viuen a/var/lib/docker/volumes/i sobreviuen al canvi.
- El cost del copy-on-write, mesurat
La teoria diu que el copy-up copia el fitxer sencer la primera vegada que el toques. Anem a mesurar-ho amb un fitxer de 512 MB ficat en una imatge.
mkdir -p /tmp/cow && cd /tmp/cow
printf 'FROM alpine:3\nRUN dd if=/dev/zero of=/gran.bin bs=1M count=512\n' > Dockerfile
docker build -q -t prova-cow .
# Un byte sobre un fitxer que viu en una capa inferior
docker run --rm prova-cow sh -c 'time dd if=/dev/zero of=/gran.bin bs=1 count=1 conv=notrunc 2>/dev/null'
# El mateix byte, sobre un fitxer que ja és a la capa d'escriptura
docker run --rm prova-cow sh -c 'cp /gran.bin /c.bin; time dd if=/dev/zero of=/c.bin bs=1 count=1 conv=notrunc 2>/dev/null'
# I l'espai que ha costat aquell byte
docker run -d --name cow prova-cow sh -c 'dd if=/dev/zero of=/gran.bin bs=1 count=1 conv=notrunc; sleep 30'
sleep 3 && docker ps -s --filter name=cow --format '{{.Names}}\t{{.Size}}' && docker rm -f cowreal 0m 1.94s <- primera escriptura: copy-up de 512 MB
real 0m 0.00s <- el fitxer ja era a upperdir
cow 512MB (virtual 528MB)Gairebé dos segons per escriure un byte, i 512 MB de capa d'escriptura consumits.
Aquest és el cost real del copy-on-write, i explica tres regles que ja havies aplicat sense conèixer-ne el perquè:
| Regla | Motiu real |
|---|---|
| No modificar fitxers grans de la imatge | Cada primera escriptura copia el fitxer sencer |
Fer servir COPY --chown en comptes d'un RUN chown -R posterior |
chown toca les metadades de cada fitxer i dispara un copy-up massiu |
| Les bases de dades van en volums | Escriuen constantment en fitxers grans |
- Per què les bases de dades exigeixen volums
PostgreSQL escriu sense parar en fitxers de dades de desenes o centenars de megabytes. Si /var/lib/postgresql/data fos a la capa d'escriptura, cada modificació d'una pàgina dispararia un copy-up del fitxer sencer la primera vegada, i el rendiment seria catastròfic.
Un volum evita OverlayFS del tot: és un bind mount a un directori del host (/var/lib/docker/volumes/<nom>/_data), muntat sobre el punt corresponent. Les escriptures van directes al sistema de fitxers del host, sense capes ni copy-up.
overlay on / type overlay (rw,relatime,lowerdir=...,upperdir=...)
/dev/sda2 on /var/lib/postgresql/data type ext4 (rw,relatime)Aquí tens la prova: mentre / és overlay, /var/lib/postgresql/data és directament el sistema de fitxers del host. Per això les imatges oficials de bases de dades declaren aquell punt com a VOLUME: si t'oblides de muntar-lo, si més no eviten la penalització creant un volum anònim.
- El driver
local i els seus driver_opts
local i els seus driver_optsEl driver de volums per defecte s'anomena local i admet opcions que gairebé ningú no fa servir, tot i que són sorprenentment potents: són les mateixes de la comanda mount de Linux.
# Volum sobre un directori concret del host (bind mount amb nom)
docker volume create --driver local \
--opt type=none --opt device=/srv/aurora/dades --opt o=bind aurora-a-srv
# Volum en memòria, limitat a 64 MB
docker volume create --driver local \
--opt type=tmpfs --opt device=tmpfs --opt o=size=64m,uid=1000 aurora-temporal| Opció | Significat |
|---|---|
type |
Tipus de sistema de fitxers: none (bind), tmpfs, nfs, cifs… |
device |
Origen: ruta del host, tmpfs, o :/ruta/exportada a NFS |
o |
Opcions de muntatge separades per comes: bind, ro, size, uid, addr… |
La diferència amb un bind mount corrent és de gestió: un volum amb nom apareix a docker volume ls, admet etiquetes, es pot declarar external i no depèn de la ruta relativa del projecte.
- Muntar NFS i
tmpfs com a volum
tmpfs com a volumUn volum NFS permet que diversos hosts comparteixin les mateixes dades, una cosa impossible amb un volum local:
# compose.yaml (fragment)
volumes:
aurora-portades:
driver: local
driver_opts:
type: nfs
o: "addr=10.0.0.20,rw,nfsvers=4,soft,timeo=30"
device: ":/exportat/aurora/portades"Tres avisos de camp. El muntatge passa en arrencar el contenidor: si el servidor NFS no respon, el contenidor no arrenca. Fes servir soft i un timeo raonable perquè una fallada de xarxa produeixi un error i no un procés penjat per sempre en estat D. I mai no posis les dades de PostgreSQL a NFS: el bloqueig de fitxers per xarxa no ofereix les garanties que una base de dades necessita, i la corrupció és qüestió de temps. Per a fitxers estàtics —les portades del catàleg— és perfecte.
- Plugins de tercers i declaració a Compose
Un volume driver és un plugin del daemon que atén les peticions de muntatge. Docker porta local; la resta s'instal·la:
docker plugin install --grant-all-permissions rclone/docker-volume-rclone:amd64
docker plugin ls # ID NAME ENABLED -> 9f2c1a rclone/docker-volume-rclone true| Família de plugin | Exemples | Per a què |
|---|---|---|
| Emmagatzematge en xarxa | local amb NFS/CIFS, netshare |
Compartir entre hosts de la mateixa xarxa |
| Objectes al núvol | rclone, s3fs |
S3, GCS o Azure Blob com si fossin directoris |
| Blocs al núvol | Plugins d'EBS, Cinder | Discos que segueixen el contenidor entre nodes |
| Instantànies | Plugins sobre ZFS o Btrfs | Còpies instantànies i clonatge |
A Compose es declaren igual que qualsevol altre volum, amb driver: rclone i els seus driver_opts (remote: "s3aurora:copies"). L'avís important: un plugin de volum és programari privilegiat dins del teu daemon. Instal·la només plugins d'origen verificat i tracta'ls amb el mateix criteri amb què aprovaries una dependència de producció.
- Volums
external compartits entre piles
external compartits entre pilesCompose anteposa el nom del projecte als volums que crea (aurora-libros_aurora-dades). Quan un volum ha d'existir fora del cicle de vida del projecte —o compartir-se amb una altra pila—, es declara external:
Dues conseqüències molt pràctiques. La primera: docker compose down -v no esborra un volum external, cosa que el converteix en una xarxa de seguretat barata per a les dades que no et pots permetre perdre. La segona: una altra pila —per exemple, un projecte separat d'informes— pot muntar el mateix volum en mode :ro i llegir les dades sense tocar la plataforma principal.
- Estratègia de còpies de seguretat d'Aurora Libros
Hi ha dues maneres de copiar les dades d'aurora-db, i no són intercanviables:
| Aspecte | Còpia lògica (pg_dump) |
Còpia de fitxers (tar del volum) |
|---|---|---|
| Servei aturat | No: en calent | Sí, perquè sigui consistent |
| Què produeix | SQL o format propi de PostgreSQL | Arxiu tar amb el directori de dades |
| Mida | Petita (comprimeix molt bé) | Gran: inclou índexs i espai lliure |
| Restauració | Requereix un servidor arrencat | Es bolca i s'arrenca |
| Canvi de versió major | Sí: de PostgreSQL 16 a 17 sense problema | No: format binari lligat a la versió |
| Restaura una sola taula | Sí | No |
| Velocitat en bases grans | Lenta | Ràpida |
Còpia lògica, en calent:
docker compose exec -T aurora-db \
pg_dump -U aurora -d aurora_llibres --format=custom --compress=9 \
> ~/copies/aurora-$(date +%Y%m%d-%H%M).dump # -> aurora-20260805-2310.dump, 18KEl -T és obligatori: sense ell, exec assigna un pseudoterminal i corromp el flux binari amb traduccions de final de línia. És l'error clàssic d'aquesta operació i no dona cap avís: el fitxer sembla correcte i falla en restaurar.
Còpia del volum a nivell de fitxer:
docker compose stop aurora-db # imprescindible per a la consistència
docker run --rm \
-v aurora-libros_aurora-dades:/dades:ro \
-v "$HOME/copies":/sortida \
alpine:3 tar czf /sortida/volum-$(date +%Y%m%d).tar.gz -C /dades .
docker compose start aurora-dbPer què cal aturar el servei: PostgreSQL manté pàgines modificades en memòria i escriu de manera asíncrona. Un tar sobre un directori de dades viu captura uns fitxers en un instant i uns altres en un altre, produint un conjunt incoherent que pot restaurar sense errors i corrompre's dies després. Amb el servei aturat, el directori està quiet i la còpia és vàlida.
- Script de còpia amb rotació i restauració verificada
#!/usr/bin/env bash
# copia-aurora.sh — còpia lògica amb rotació i verificació de restauració
set -euo pipefail
DESTI="${DESTI:-/srv/copies/aurora}"
RETENCIO_DIES="${RETENCIO_DIES:-14}"
FITXER="$DESTI/aurora-$(date +%Y%m%d-%H%M).dump"
mkdir -p "$DESTI"
echo "==> Còpia lògica d'aurora_llibres"
docker compose exec -T aurora-db \
pg_dump -U aurora -d aurora_llibres --format=custom --compress=9 > "$FITXER"
# Una còpia de 0 bytes és una fallada silenciosa: comprova-ho sempre
[ -s "$FITXER" ] || { echo "ERROR: còpia buida"; exit 1; }
echo "==> Verificant la restauració en una base de dades d'un sol ús"
docker run -d --rm --name verifica-copia \
-e POSTGRES_USER=aurora -e POSTGRES_PASSWORD=verifica -e POSTGRES_DB=verifica \
--tmpfs /var/lib/postgresql/data postgres:16-alpine >/dev/null
for i in $(seq 1 30); do
docker exec verifica-copia pg_isready -U aurora -d verifica -q && break || sleep 1
done
docker exec -i verifica-copia pg_restore -U aurora -d verifica --no-owner < "$FITXER"
TOTAL=$(docker exec verifica-copia psql -U aurora -d verifica -tAc 'SELECT count(*) FROM llibres')
docker rm -f verifica-copia >/dev/null
[ "$TOTAL" -ge 9 ] || { echo "ERROR: la còpia només té $TOTAL llibres"; exit 1; }
echo "==> Restauració verificada: $TOTAL llibres"
echo "==> Rotació: eliminant còpies de més de $RETENCIO_DIES dies"
find "$DESTI" -name 'aurora-*.dump' -mtime "+$RETENCIO_DIES" -print -delete==> Còpia lògica d'aurora_llibres
==> Verificant la restauració en una base de dades d'un sol ús
==> Restauració verificada: 9 llibres
==> Rotació: eliminant còpies de més de 14 diesEl que converteix aquest script en una cosa seriosa no és la còpia, és la verificació: cada execució restaura el fitxer acabat de crear en un PostgreSQL efímer a tmpfs i compta les files. Si la còpia era buida, truncada o corrupta, l'script falla avui, no el dia del desastre.
Grava't la regla: una còpia que no s'ha restaurat mai no és una còpia, és una carpeta amb esperança a dins.
- Espai al disc i
data-root
data-rootTot el que Docker desa viu sota /var/lib/docker:
| Subdirectori | Contingut | Com es neteja |
|---|---|---|
overlay2/ |
Capes d'imatges i de contenidors | docker image prune -a, container prune |
volumes/ |
Volums amb nom i anònims | docker volume prune (amb compte) |
containers/ |
Metadades i logs en JSON | Rotació de logs (lliçó 05-06) |
buildkit/ |
Memòria cau de construcció | docker builder prune |
image/, network/ |
Índexs i metadades | Es gestionen sols |
4.1G /var/lib/docker/overlay2
1.3G /var/lib/docker/volumes
612M /var/lib/docker/buildkit
88M /var/lib/docker/containersSi containers/ és enorme, el culpable són els logs sense rotar (ho resoldràs a 05-06). Si ho és overlay2/, són imatges antigues. Per moure el magatzem a un disc més gran:
sudo systemctl stop docker
sudo rsync -aHAX /var/lib/docker/ /dades/docker/
printf '{\n "data-root": "/dades/docker"\n}\n' | sudo tee /etc/docker/daemon.json
sudo systemctl start docker
docker info --format 'Docker Root Dir: {{.DockerRootDir}}' # -> /dades/dockerFes servir rsync -aHAX i no cp: cal preservar enllaços durs, atributs estesos i permisos, o les capes quedaran inservibles. Comprova que tot funciona abans d'esborrar el directori antic.
- Rendiment i permisos (UID/GID)
Elecció de muntatge per rendiment, de millor a pitjor per a escriptura intensiva:
| Muntatge | Rendiment d'escriptura | Ús recomanat |
|---|---|---|
tmpfs |
Màxim (RAM) | Dades efímeres, proves, fitxers temporals |
| Volum amb nom | Natiu del sistema de fitxers | Bases de dades i tota dada persistent |
| Bind mount (Linux) | Natiu | Codi en desenvolupament, configuració |
| Bind mount (macOS/WSL 2 creuant la frontera) | Dolent | Evitar per a molts fitxers petits |
| Capa d'escriptura del contenidor | El pitjor: copy-up | Res que s'escrigui de manera repetida |
Els permisos són l'altra meitat del problema. Un volum buit hereta el propietari del punt de muntatge de la imatge; un volum amb dades conserva els seus, i aurora-api corre com l'usuari node (UID 1000), així que un volum creat per root li resulta il·legible.
docker volume create aurora-adjunts
docker run --rm -v aurora-adjunts:/dades alpine:3 stat -c '%u:%g' /dades # -> 0:0
docker run --rm -v aurora-adjunts:/dades alpine:3 chown -R 1000:1000 /dades # una sola vegada
docker run --rm -u 1000 -v aurora-adjunts:/dades alpine:3 sh -c 'touch /dades/ok && echo OK'Amb bind mounts la solució és diferent, perquè el propietari el fixa el host: o bé alinees l'UID del contenidor amb el del teu usuari (user: "${UID}:${GID}" a Compose), o bé ajustes els permisos al host. I recorda de la lliçó 03-06 que el kernel només entén números: el nom node no significa res fora del contenidor.
Errors Habituals i Consells
Escriure dades persistents a la capa del contenidor. Rendiment pèssim per copy-up i pèrdua total en recrear-lo.
Fer tar d'un volum amb la base de dades en marxa. La còpia sembla correcta i és incoherent. Atura el servei o fes servir pg_dump.
Oblidar -T a docker compose exec pg_dump. El pseudoterminal corromp el bolcat binari sense avisar.
No provar mai una restauració. El dia de l'incident descobreixes que fa mesos que guardes fitxers buits.
Executar docker volume prune sense mirar. Esborra tot volum no fet servir per cap contenidor, i un volum d'una pila aturada entra dins d'aquella definició. Declara external allò crític.
Canviar el storage driver sense còpia prèvia, o posar dades de PostgreSQL a NFS. En el primer cas desapareixen imatges i contenidors de l'inventari; en el segon, el bloqueig de fitxers per xarxa no dona les garanties que una base de dades necessita.
Consell: etiqueta els volums en crear-los (--label criticitat=alta) i filtra per aquella etiqueta abans de qualsevol neteja: docker volume ls --filter label=criticitat=alta. Un minut d'etiquetatge evita l'esborrat que no té marxa enrere.
Exercicis
Exercici 1. Demostra el copy-on-write en dues direccions: localitza l'upperdir d'aurora-api, crea un fitxer dins del contenidor i troba'l al disc del host; després mesura el cost de modificar un byte d'un fitxer de 256 MB que vingui a la imatge, i compara'l amb modificar un byte d'un fitxer ja present a la capa d'escriptura.
Exercici 2. Munta el cicle complet de còpia i restauració d'aurora-db: fes una còpia lògica, destrueix les dades esborrant el volum, restaura i comprova que els nou títols hi tornen a ser. Explica en quin punt exacte la plataforma hauria quedat inservible sense la còpia.
Exercici 3. Converteix aurora-dades en un volum external, demostra que docker compose down -v ja no l'esborra i explica quina protecció aporta això i quina n'és la contrapartida.
Solucions
Solució 1.
up=$(docker inspect aurora-libros-aurora-api-1 --format '{{.GraphDriver.Data.UpperDir}}')
docker compose exec aurora-api sh -c 'echo "hola capes" > /tmp/prova.txt'
sudo cat "$up/tmp/prova.txt"
docker diff aurora-libros-aurora-api-1 | grep provaprintf 'FROM alpine:3\nRUN dd if=/dev/zero of=/g.bin bs=1M count=256\n' > /tmp/Dockerfile.cow
docker build -q -t cow256 -f /tmp/Dockerfile.cow /tmp
docker run --rm cow256 sh -c 'time dd if=/dev/zero of=/g.bin bs=1 count=1 conv=notrunc 2>/dev/null'
docker run --rm cow256 sh -c 'cp /g.bin /c.bin; time dd if=/dev/zero of=/c.bin bs=1 count=1 conv=notrunc 2>/dev/null'Un segon davant de zero, per escriure exactament el mateix byte. La diferència és el copy-up: en el primer cas el fitxer viu en un lowerdir de només lectura i el kernel ha de copiar els 256 MB sencers a l'upperdir abans de permetre l'escriptura; en el segon, cp ja l'havia portat a la capa d'escriptura. Extrapola: PostgreSQL escrivint sense parar en fitxers de dades sense un volum pagaria aquell peatge una vegada i una altra, a més de multiplicar l'espai ocupat. Aquí es veu, en un segon de rellotge, per què la decisió de la lliçó 03-06 no era una convenció sinó una necessitat física.
Solució 2.
docker compose exec -T aurora-db pg_dump -U aurora -d aurora_llibres -Fc > /tmp/aurora.dump
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'
docker compose down -v # el desastre
docker volume ls --filter name=aurora-dades -q | wc -l
docker compose up -d --wait
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'Aquí hi ha un matís que confon molta gent: després del down -v la base de dades torna amb 9 llibres sense haver restaurat res, perquè el volum s'ha recreat buit i PostgreSQL ha executat de nou db/init.sql. Això és exactament el que fa perillosa la situació: sembla que no s'ha perdut res.
El que sí que s'ha perdut són les dades afegides després de la inicialització, que és tot el que importa en producció:
docker compose exec aurora-db psql -U aurora -d aurora_llibres \
-c "INSERT INTO llibres (titol, autor, any, isbn) VALUES ('Trafalgar','B. Pérez Galdós',1873,'978-84-000001-0')"
docker compose exec -T aurora-db pg_dump -U aurora -d aurora_llibres -Fc > /tmp/aurora10.dump
docker compose down -v && docker compose up -d --wait
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'
docker compose exec -T aurora-db pg_restore -U aurora -d aurora_llibres --clean --if-exists --no-owner < /tmp/aurora10.dump
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'Després del desastre en queden 9 (els d'init.sql); després de restaurar, els 10 reals. El punt exacte en què la plataforma hauria quedat inservible és el down -v: el -v esborra els volums, i amb ells l'únic lloc on existien les dades afegides pels usuaris. Sense /tmp/aurora10.dump, aquella fila no es recupera d'enlloc.
Solució 3.
docker compose down && docker volume create --label criticitat=alta aurora-dades-ext
docker run --rm -v aurora-libros_aurora-dades:/origen:ro -v aurora-dades-ext:/desti \
alpine:3 sh -c 'cp -a /origen/. /desti/'docker compose up -d --wait
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'
docker compose down -v
docker volume ls --filter name=aurora-dades-ext --format '{{.Name}}'
docker compose up -d --wait
docker compose exec aurora-db psql -U aurora -d aurora_llibres -tAc 'SELECT count(*) FROM llibres'El down -v no ha esborrat el volum i les dades continuen intactes: Compose es nega a destruir el que no ha creat. La protecció és real i costa dues línies de YAML, així que per al volum de dades d'una plataforma en producció és una decisió gairebé automàtica.
La contrapartida té dues cares. La primera, operativa: el volum deixa de crear-se sol, i qui desplegui per primera vegada en un servidor nou ha d'executar docker volume create abans de l'up, o Compose fallarà amb external volume not found. La segona, conceptual: perds la reproductibilitat d'un entorn des de zero. En desenvolupament això molesta —el reset de la lliçó 04-07 deixa de funcionar—, així que la pràctica sensata és declarar external només a compose.prod.yaml, deixant que l'entorn local continuï sent d'un sol ús.
Conclusió
Ja saps què passa sota -v. Un storage driver apila les capes d'una imatge i aplica copy-on-write, i overlay2 ho fa amb quatre directoris que has vist al disc: els lowerdir de només lectura de la imatge, l'upperdir on apareix cada fitxer que escriu el contenidor, el merged que és el que el procés veu com a / i el workdir intern del kernel. D'allà surten les tres regles de resolució, inclosa la dels whiteouts que explica per què esborrar un fitxer en una capa posterior no allibera espai. Coneixes la taula completa de drivers —btrfs, zfs, el retirat devicemapper, fuse-overlayfs per a rootless i el lentíssim vfs— i saps que canviar de driver deixa invisibles totes les teves imatges.
I has mesurat el copy-on-write: gairebé dos segons i 512 MB de capa per escriure un sol byte en un fitxer que venia a la imatge. Aquesta xifra converteix en física el que era una recomanació: una base de dades escriu constantment en fitxers grans, per tant va en un volum, que evita OverlayFS i escriu directe al sistema de fitxers del host. Saps esprémer el driver local amb els seus driver_opts —bind amb nom, tmpfs amb mida, NFS per a les portades i mai per a PostgreSQL—, declarar plugins de tercers a Compose i fer servir volums external perquè down -v no pugui endur-se per davant les dades de producció. T'endús a més una estratègia de còpies que és una estratègia i no una intenció: la taula que distingeix la còpia lògica en calent amb pg_dump de la còpia de fitxers amb tar —i per què la segona exigeix aturar el servei—, un script amb rotació que restaura i compta files a cada execució, la regla que una còpia que no s'ha restaurat mai no és una còpia, i el control de l'espai a /var/lib/docker amb data-root.
A la lliçó 05-03 arriba el torn de la seguretat, i amb ella l'enduriment complet d'Aurora Libros: el model d'amenaces i les seves quatre superfícies, per què pertànyer al grup docker equival a ser root —amb l'escalada demostrada—, el mode rootless, imatges mínimes i fixades per digest, --read-only, capacitats del kernel, seccomp, escaneig de vulnerabilitats amb Docker Scout i Trivy, SBOM i signatura amb Cosign, i un compose.prod.yaml endurit línia a línia amb la seva llista de comprovació accionable.
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
