Ara mateix tens tres o quatre contenidors a la teva màquina i encara els pots portar al cap. D'aquí a un mes en tindràs trenta: els quatre serveis d'Aurora Libros, mitja dotzena de proves oblidades, contenidors d'altres projectes i un munt d'Exited de fa setmanes ocupant disc i noms. Sense eines de gestió, aquell docker ps -a es converteix en una paret de text impossible de llegir, i el docker rm massiu que executes a les onze de la nit s'emporta per davant alguna cosa que necessitaves.
Aquesta lliçó és la de l'operació diària. Espremeràs docker ps fins al fons —columna per columna, amb els seus filtres i les seves plantilles—, muntaràs un tauler de control dels quatre serveis d'Aurora Libros, aprendràs a compondre comandes amb -q per operar sobre desenes de contenidors sense destrossar res, a copiar fitxers entre el host i un contenidor amb docker cp —amb la qual cosa per fi ompliràs la taula llibres amb els vuit títols—, a veure amb docker diff què ha canviat un contenidor respecte a la seva imatge, i a entendre per què docker commit és una temptació que cal resistir.
Contingut
docker ps: les set columnes, una a una- Opcions de llistat:
-a,-q,-s,-n,-l - Filtrar amb
--filter - Donar format amb
--formati plantilles Go - Etiquetes: organitzar la flota amb
--label - Compondre comandes amb
-q(i fer-ho amb cap) - Esborrar contenidors:
rm,-f,-vicontainer prune - Reanomenar i modificar en calent:
renameiupdate docker cp: moure fitxers en els dos sentitsdocker diff: què ha canviat respecte a la imatgedocker commiti per què no l'has de fer servir- El tauler de control d'Aurora Libros
docker ps: les set columnes, una a una
docker ps: les set columnes, una a unaCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f8a1c9e7b2d postgres:16-alpine "docker-entrypoint.s…" 35 minutes ago Up 35 minutes 127.0.0.1:5432->5432/tcp aurora-db
9d4b7e2f1a6c redis:7-alpine "docker-entrypoint.s…" 32 minutes ago Up 4 minutes (healthy) 127.0.0.1:6379->6379/tcp aurora-cache| Columna | Què és exactament | Detalls que convé saber |
|---|---|---|
| CONTAINER ID | Els 12 primers caràcters de l'ID de 64 | N'hi ha prou d'escriure els primers que siguin únics: docker stop 3f8 funciona |
| IMAGE | La referència de la imatge tal com es va escriure | Si vas arrencar amb un digest, veuràs el digest; si l'etiqueta es va moure després, aquest text ja no diu la veritat |
| COMMAND | La comanda efectiva: ENTRYPOINT + CMD |
Apareix truncada amb …. Es veu sencera amb --no-trunc |
| CREATED | Quan es va crear el contenidor | No és quan es va arrencar: un contenidor creat fa un mes i arrencat fa un minut posa "5 weeks ago" |
| STATUS | Estat i temps que hi porta | Up 35 minutes, Exited (0) 2 hours ago, Up 4 minutes (healthy), Created, Paused |
| PORTS | Publicacions actives | 127.0.0.1:5432->5432/tcp és host→contenidor. Si només posa 5432/tcp, està exposat però no publicat |
| NAMES | El nom assignat o inventat | Únic a la màquina |
Dues observacions sobre la sortida de dalt, que serveixen de repàs:
aurora-cacheposaUp 4 minutesi noUp 32 minutesperquè el vas reiniciar a la lliçó anterior: el comptador deSTATUSes posa a zero amb cada arrencada, mentre queCREATEDno es mou.- El
(healthy)d'aurora-cacheno apareix per art de màgia: la imatge oficial de Redis 7 porta el seu propiHEALTHCHECK.aurora-dbno en mostra res perquè la imatge de PostgreSQL no el defineix. La salut s'estudia a fons a la lliçó 03-04.
Per veure la comanda completa:
- Opcions de llistat:
-a, -q, -s, -n, -l
-a, -q, -s, -n, -l| Opció | Què fa | Ús típic |
|---|---|---|
-a, --all |
Mostra tots, inclosos Exited i Created |
Trobar el contenidor que va morir |
-q, --quiet |
Només els IDs, un per línia | Compondre amb altres comandes |
-s, --size |
Afegeix la columna SIZE |
Saber quant ocupa de debò |
-n N |
Els N últims creats, corrent o no | docker ps -n 3 |
-l, --latest |
L'últim creat | docker logs $(docker ps -lq) |
--no-trunc |
No trunca IDs ni comandes | Copiar un ID complet |
-s: la mida real d'un contenidor
NAMES IMAGE SIZE
aurora-cache redis:7-alpine 0B (virtual 41.2MB)
aurora-db postgres:16-alpine 127kB (virtual 278MB)Aquesta columna té dos números i la diferència entre tots dos és la lliçó 01-05 feta comanda:
- El primer (
0B,127kB) és la capa d'escriptura: el que aquest contenidor ha escrit per damunt de la imatge. És l'única cosa que li pertany en exclusiva i l'única que es perd en esborrar-lo. - El
virtualés la mida total que veu el contenidor: la seva capa d'escriptura més totes les capes de la imatge, que són compartides i de només lectura.
Deu contenidors de redis:7-alpine no ocupen 412 MB, sinó 41,2 MB més deu capes d'escriptura minúscules. I aurora-db amb els seus 127 kB d'escriptura crida l'atenció: acabes de crear una base de dades sencera, on són les dades? En un volum anònim que la imatge oficial declara, i que no compta com a capa d'escriptura. Retén aquesta pregunta: és el cor de la lliçó 03-06.
- Filtrar amb
--filter
--filter--filter (o -f) accepta parells clau=valor i es pot repetir. Els filtres disponibles:
| Filtre | Exemple | Què selecciona |
|---|---|---|
status |
--filter status=exited |
Per estat: created, running, paused, restarting, exited, dead |
name |
--filter name=aurora |
Nom que conté aquesta cadena (és una subcadena, no una igualtat) |
ancestor |
--filter ancestor=redis:7-alpine |
Contenidors creats a partir d'aquesta imatge |
label |
--filter label=projecte=aurora-libros |
Per etiqueta, amb valor o sense |
exited |
--filter exited=1 |
Els que van sortir amb aquell codi |
health |
--filter health=unhealthy |
Per estat de salut: starting, healthy, unhealthy, none |
before / since |
--filter since=aurora-db |
Creats abans/després d'aquell contenidor |
id |
--filter id=3f8a1c9e7b2d |
Per ID |
volume |
--filter volume=aurora-dades |
Els que munten aquell volum (lliçó 03-06) |
network |
--filter network=aurora-net |
Els connectats a aquella xarxa (lliçó 03-05) |
publish / expose |
--filter publish=5432 |
Els que publiquen o exposen aquell port |
Receptes llestes per copiar:
# Tot el que sigui d'Aurora Libros, viu o mort
docker ps -a --filter name=aurora
# Només el que està corrent d'una imatge concreta
docker ps --filter ancestor=postgres:16-alpine
# Contenidors que van fallar: van sortir amb un codi diferent de 0
docker ps -a --filter status=exited --filter exited=1
# Contenidors malalts ara mateix
docker ps --filter health=unhealthy
# El creat després d'aurora-db (útil per acotar una sessió de treball)
docker ps -a --filter since=aurora-dbExemple real:
Dos avisos sobre el comportament dels filtres:
- Diversos
--filterdiferents es combinen amb I lògic.--filter status=running --filter name=auroraexigeix les dues condicions. - Diversos valors del mateix filtre es combinen amb O lògic.
--filter status=exited --filter status=createdretorna els de qualsevol dels dos estats. nameés una subcadena, no una igualtat.--filter name=aurora-dbtambé trobaaurora-db-copia. Si necessites exactitud, fes servir una expressió ancorada:--filter name=^aurora-db$.
- Donar format amb
--format i plantilles Go
--format i plantilles Go--format fa servir plantilles del llenguatge Go, les mateixes que ja vas emprar amb docker image ls a la lliçó 02-05.
| Marcador | Contingut |
|---|---|
{{.ID}} |
ID curt |
{{.Names}} |
Nom |
{{.Image}} |
Imatge |
{{.Command}} |
Comanda efectiva |
{{.CreatedAt}} |
Data completa de creació |
{{.RunningFor}} |
Temps transcorregut en text |
{{.Status}} |
Estat amb el seu temps |
{{.State}} |
Només l'estat (running, exited…) |
{{.Ports}} |
Ports publicats |
{{.Size}} |
Mida (requereix -s) |
{{.Labels}} |
Totes les etiquetes |
{{.Label "clau"}} |
El valor d'una etiqueta |
{{.Mounts}} |
Volums muntats |
{{.Networks}} |
Xarxes connectades |
La paraula table al principi activa la capçalera i l'alineació en columnes:
Sense table, la sortida és text lliure, perfecta per fer-hi scripts:
I hi ha dos formats preconstruïts molt socorreguts:
docker ps --format json | head -1
docker ps --format "{{json .}}" | jq -r '.Names + " | " + .Status'{"Command":"\"docker-entrypoint.s…\"","CreatedAt":"2026-08-04 19:28:41 +0200 CEST","ID":"3f8a1c9e7b2d",...}
aurora-db | Up 41 minutes
aurora-cache | Up 10 minutesSi un format t'agrada, fes-lo permanent a ~/.docker/config.json:
A partir d'aquell moment, un docker ps sense més fa servir el teu format. És un dels ajustos que més agraeix l'ús diari.
- Etiquetes: organitzar la flota amb
--label
--labelQuan a la mateixa màquina hi conviuen contenidors de tres projectes, filtrar per nom deixa de ser fiable. Les etiquetes són metadades arbitràries que assignes en crear el contenidor:
docker run -d --name prova-etiquetes \
--label projecte=aurora-libros \
--label component=demo \
--label entorn=local \
alpine:3.20 sleep 300I després hi filtres amb precisió quirúrgica:
docker ps --filter label=projecte=aurora-libros --format "{{.Names}}"
docker ps --filter label=component --format "{{.Names}}"
docker rm -f prova-etiquetes--filter label=clau=valor exigeix el valor exacte; --filter label=clau només exigeix que l'etiqueta existeixi.
Etiquetarem de debò la flota d'Aurora Libros. Com que les etiquetes, igual que els ports i les variables, es fixen en crear el contenidor i no s'hi poden afegir després (lliçó 03-01), cal recrear. No passa res: aurora-db encara no té dades a perdre.
docker rm -f aurora-db aurora-cache
docker run -d --name aurora-db \
--label projecte=aurora-libros \
--label component=base-de-dades \
--label entorn=local \
-e POSTGRES_USER=aurora \
-e POSTGRES_PASSWORD=aurora_secreta \
-e POSTGRES_DB=aurora_llibres \
-p 127.0.0.1:5432:5432 \
postgres:16-alpine
docker run -d --name aurora-cache \
--label projecte=aurora-libros \
--label component=cache \
--label entorn=local \
-p 127.0.0.1:6379:6379 \
redis:7-alpinedocker ps --filter label=projecte=aurora-libros \
--format 'table {{.Names}}\t{{.Label "component"}}\t{{.Status}}'Una convenció d'etiquetes que funciona bé i que farem servir a tot el curs:
| Etiqueta | Valors a Aurora Libros | Per a què serveix |
|---|---|---|
projecte |
aurora-libros |
Separar d'altres projectes de la màquina |
component |
base-de-dades, cache, api, web |
Identificar el paper de cada contenidor |
entorn |
local, proves, produccio |
Distingir instàncies del mateix servei |
Amb aquestes tres etiquetes, operacions com "atura tot el d'Aurora Libros en local sense tocar res més" es tornen trivials, i és exactament el que Docker Compose farà per tu automàticament al mòdul 4: les seves etiquetes com.docker.compose.project són aquest mateix mecanisme.
- Compondre comandes amb
-q (i fer-ho amb cap)
-q (i fer-ho amb cap)docker ps -q imprimeix només IDs, i això el converteix en l'entrada de qualsevol altra comanda:
Receptes que es fan servir a diari:
# Aturar tots els contenidors d'una imatge concreta
docker stop $(docker ps -q --filter ancestor=postgres:16-alpine)
# Esborrar tots els contenidors aturats
docker rm $(docker ps -aq --filter status=exited)
# Aturar tota la flota d'Aurora Libros
docker stop $(docker ps -q --filter label=projecte=aurora-libros)
# Reiniciar només els que estan malalts
docker restart $(docker ps -q --filter health=unhealthy)I ara les tres precaucions, perquè aquestes comandes són esmolades:
Primera: si el filtre no troba res, la comanda falla.
Molest però inofensiu. S'evita comprovant abans:
IDS=$(docker ps -q --filter label=projecte=aurora-libros)
[ -n "$IDS" ] && docker stop $IDS || echo "No hi ha res per aturar"Segona: docker rm -f $(docker ps -aq) és la comanda més perillosa d'aquesta lliçó. Esborra absolutament tots els contenidors de la màquina, inclosos els d'altres projectes, i sense preguntar. Si necessites fer neteja, fes-la acotada:
Tercera: mira abans de disparar. La regla d'or és executar primer la versió que només llista:
# 1. Què tocaré exactament?
docker ps -a --filter status=exited --format "table {{.Names}}\t{{.Status}}"
# 2. Si la llista és la que esperava, llavors sí
docker rm $(docker ps -aq --filter status=exited)Aquest mig segon de més ha salvat moltes bases de dades de desenvolupament.
- Esborrar contenidors:
rm, -f, -v i container prune
rm, -f, -v i container prunedocker rm només funciona sobre contenidors aturats. Amb un en marxa:
Error response from daemon: cannot remove container "aurora-cache":
container is running: stop the container before removing or force remove| Opció | Efecte |
|---|---|
| (cap) | Només esborra contenidors aturats |
-f, --force |
Envia SIGKILL i esborra. Sense període de gràcia |
-v, --volumes |
Esborra a més els volums anònims associats (mai els que tenen nom) |
-l, --link |
Elimina un enllaç heretat, no el contenidor. Pràcticament en desús |
Sobre -f, un matís important que enllaça amb la lliçó anterior: docker rm -f no és docker stop + docker rm. Envia SIGKILL directament, sense els deu segons de gràcia. Sobre una base de dades, això és desendollar el servidor. La seqüència correcta quan hi ha dades pel mig és:
Què passa exactament en esborrar un contenidor:
| Es destrueix | Sobreviu |
|---|---|
| La capa d'escriptura i tot el que hi hagués | La imatge de la qual va sortir |
| Els registres del contenidor | Els volums amb nom (lliçó 03-06) |
| La seva configuració i el seu nom | Els fitxers del host muntats com a bind mount |
Els volums anònims, només si fas servir -v |
Els volums anònims, si no fas servir -v (queden orfes) |
docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
7d3f9a1b2c48e6015a2c9f7b3e1d8a4c6f0b2d9e7a5c3f1b8d6a4e2c9f7b5d3a
Total reclaimed space: 41.9kBEsborra tots els contenidors aturats. Val la pena repetir l'avís de la lliçó 02-05: un contenidor aturat pot ser alguna cosa que estaves depurant o una base de dades de desenvolupament que vas apagar ahir. Acota sempre que puguis:
# Només els aturats fa més de 24 hores
docker container prune --filter "until=24h"
# Només els aturats d'un projecte concret
docker container prune --filter "label=projecte=aurora-libros"
# Sense confirmació interactiva (per a scripts; fes-ho servir amb doble cura)
docker container prune -f --filter "until=168h"
- Reanomenar i modificar en calent:
rename i update
rename i updateJa vas veure docker rename a la lliçó anterior. El seu company és docker update, que sí que pot canviar coses d'un contenidor en marxa, encara que una llista molt concreta:
docker update --restart=unless-stopped aurora-db
docker update --memory 512m --memory-swap 512m aurora-dbEs pot canviar amb update |
No es pot canviar mai |
|---|---|
Memòria (--memory, --memory-swap, --memory-reservation) |
Ports publicats |
CPU (--cpus, --cpu-shares, --cpuset-cpus) |
Variables d'entorn |
Nombre de processos (--pids-limit) |
Muntatges i volums |
Política de reinici (--restart) |
Imatge, CMD o ENTRYPOINT |
Pes d'E/S de disc (--blkio-weight) |
Etiquetes i xarxes |
El detall de totes aquestes opcions de recursos i de les polítiques de reinici és el contingut de la lliçó 03-07; aquí només importa retenir la frontera: update toca el que viu als cgroups; tot el que viu als namespaces (xarxa, muntatges, entorn) es fixa en crear el contenidor.
docker cp: moure fitxers en els dos sentits
docker cp: moure fitxers en els dos sentitsUn dels dos costats porta el prefix contenidor: i l'altre és una ruta del host. Funciona en les dues direccions i també amb contenidors aturats.
Del host al contenidor: carregar el catàleg
Ha arribat el moment d'omplir la base de dades. Tens ~/aurora-libros/db/init.sql des de la lliçó 01-07, amb la taula llibres i els vuit títols:
I ara executa'l dins del contenidor:
Comprova el resultat:
docker exec aurora-db psql -U aurora -d aurora_llibres \
-c "SELECT id, titol, autor, preu FROM llibres ORDER BY id LIMIT 4;"
docker exec aurora-db psql -U aurora -d aurora_llibres -t \
-c "SELECT COUNT(*) FROM llibres;" id | titol | autor | preu
----+---------------------------------------+------------------------+--------
1 | El jardín de senderos que se bifurcan | Jorge Luis Borges | 14.50
2 | Rayuela | Julio Cortázar | 19.90
3 | Cien años de soledad | Gabriel García Márquez | 17.95
4 | La sombra del viento | Carlos Ruiz Zafón | 21.00
(4 rows)
8Els vuit llibres d'Aurora Libros són en una base de dades real, en un contenidor real. És la primera vegada en tot el curs que existeixen fora d'un fitxer .sql. Encara ningú no els pot llegir des de l'API —això arriba a la lliçó 03-05—, però ja hi són.
Un apunt de mètode: carregar l'esquema a mà amb docker cp funciona però no és la manera correcta, perquè cal repetir-ho cada vegada que recreïs el contenidor i ningú no se'n recorda. A la lliçó 03-06 ho resoldràs bé, muntant init.sql a /docker-entrypoint-initdb.d/ perquè PostgreSQL l'executi tot sol en inicialitzar-se.
Del contenidor al host: extreure un fitxer
El sentit invers és igual de fàcil i resulta imprescindible en investigar un incident:
docker cp aurora-db:/var/lib/postgresql/data/pg_hba.conf ~/aurora-libros/pg_hba.conf.copia
head -3 ~/aurora-libros/pg_hba.conf.copiaSuccessfully copied 5.12kB to /home/junior/aurora-libros/pg_hba.conf.copia
# PostgreSQL Client Authentication Configuration File
# ===================================================I un cas molt habitual: rescatar el registre d'una aplicació que —contra tota bona pràctica— escriu en un fitxer en comptes de a la sortida estàndard.
Detalls del comportament de docker cp que eviten sorpreses:
| Situació | Resultat |
|---|---|
docker cp fitxer contenidor:/ruta/ (acaba en /) |
Copia dins del directori |
docker cp fitxer contenidor:/ruta (sense /) |
Si /ruta és un directori, copia a dins; si no, crea o sobreescriu aquest fitxer |
docker cp carpeta/. contenidor:/desti |
Copia el contingut de la carpeta |
docker cp carpeta contenidor:/desti |
Copia la carpeta sencera dins de la destinació |
Amb -a/--archive |
Conserva propietari i grup (UID/GID) |
Sense -a |
Els fitxers queden com a root dins del contenidor |
Aquest últim punt mossega sovint: si copies un fitxer a un contenidor que corre amb USER node, el fitxer pertanyerà a root i l'aplicació potser no el podrà llegir. I una limitació clara: docker cp no pot copiar d'un contenidor a un altre directament; cal passar pel host.
docker diff: què ha canviat respecte a la imatge
docker diff: què ha canviat respecte a la imatgedocker diff compara el sistema de fitxers actual del contenidor amb el de la imatge de la qual va sortir:
C /tmp
A /tmp/init.sql
C /run
A /run/postgresql
A /run/postgresql/.s.PGSQL.5432
C /var/lib/postgresqlTres lletres i el seu significat:
| Lletra | Significa | Exemple |
|---|---|---|
| A | Added: fitxer o directori nou | /tmp/init.sql, el que acabes de copiar |
| C | Changed: modificat (o un directori el contingut del qual va canviar) | /tmp, perquè ara conté alguna cosa nova |
| D | Deleted: esborrat respecte a la imatge | Un fitxer de configuració que es va substituir |
És la manifestació visible del copy-on-write de la lliçó 01-05: el que veus aquí és exactament el contingut de la capa d'escriptura, i per això docker diff i la columna SIZE de docker ps -s parlen del mateix.
I ara l'observació important:
Ni una línia. Acabes de crear una taula i vuit registres, i el directori de dades de PostgreSQL no apareix al diff. La raó és que /var/lib/postgresql/data no està a la capa d'escriptura: la imatge oficial hi declara un VOLUME, així que Docker va crear un volum anònim i el va muntar en aquella ruta. I docker diff mai no mira dins dels muntatges.
Això és exactament el que anticipava la lliçó 02-04 en parlar de per què VOLUME en un Dockerfile té efectes secundaris, i és la porta d'entrada a la lliçó 03-06: hi ha dades que no viuen ni a la imatge ni a la capa d'escriptura, sinó en un tercer lloc. Un lloc que ara mateix, per a aurora-db, és anònim i fràgil.
Un cas d'ús molt pràctic de docker diff: descobrir què escriu una aplicació de la qual no et refies.
docker run -d --name diff-demo nginx:alpine
sleep 2 && curl -s localhost > /dev/null 2>&1
docker diff diff-demo
docker rm -f diff-demoC /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /run
A /run/nginx.pid
C /var/cache/nginx
A /var/cache/nginx/client_tempEn deu línies saps que Nginx modifica la seva configuració en arrencar (ho fa el seu docker-entrypoint.sh), crea un fitxer de PID i diversos directoris de memòria cau. És informació valuosíssima quan vulguis fer el sistema de fitxers de només lectura per seguretat, cosa que veuràs a la lliçó 05-03.
docker commit i per què no l'has de fer servir
docker commit i per què no l'has de fer servirdocker commit converteix l'estat actual d'un contenidor en una imatge nova:
docker commit --message "Catàleg carregat a mà" aurora-db aurora-db:amb-dades
docker image ls aurora-db --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}"sha256:8f2e9c1a7b34d6058e2f9a1c7b3d5e8a0c2f4b6d8e0a2c4f6b8d0e2a4c6f8b0d2
REPOSITORY:TAG SIZE
aurora-db:amb-dades 278MBFunciona. I precisament per això és perillós. Aquests són els motius pels quals no es construeixen imatges així, reprenent tot el mòdul 2:
| Problema | Conseqüència |
|---|---|
| No és reproduïble | No existeix cap fitxer que descrigui com es va arribar a aquell estat. Si demà necessites la mateixa imatge amb Node 22.14, no hi ha manera de regenerar-la |
| No és auditable | docker image history mostrarà una capa enorme amb el comentari que vas escriure, sense dir què s'hi va instal·lar, què es va esborrar ni d'on venia |
| No es versiona | Un Dockerfile viu a Git, es revisa en una pull request i té historial. Un commit viu al cap de qui el va fer |
| Arrossega brossa | Fitxers temporals, historial de shell, registres, credencials escrites durant la sessió de depuració... tot es cou dins la imatge |
| Pesa de més | És una capa monolítica que trenca la memòria cau i el compartir capes que tant vas cuidar a la lliçó 02-02 |
| Trenca la cadena de confiança | Ningú no pot respondre a "què hi ha aquí dins?" sense obrir-ho i mirar |
Al vocabulari de l'ofici, una imatge així s'anomena imatge artesanal o snowflake, i és l'equivalent contenidoritzat d'aquell servidor que ningú no gosava reiniciar. Té, això sí, un ús legítim:
# Forense: congelar un contenidor trencat ABANS d'esborrar-lo, per investigar-lo amb calma
docker commit aurora-api aurora-api:forense-2026-08-04
docker rm aurora-api
docker run --rm -it --entrypoint sh aurora-api:forense-2026-08-04Desar l'escena del crim abans de netejar-la. Per a això sí, i per a res més.
- El tauler de control d'Aurora Libros
Tanquem ajuntant tot el de la lliçó en una comanda que faràs servir a diari:
docker ps -a --filter label=projecte=aurora-libros \
--format 'table {{.Label "component"}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}'COMPONENT NAMES STATUS PORTS
cache aurora-cache Up 22 minutes 127.0.0.1:6379->6379/tcp
base-de-dades aurora-db Up 22 minutes 127.0.0.1:5432->5432/tcpConverteix-la en un àlies permanent al teu ~/.bashrc o ~/.zshrc:
alias aurora='docker ps -a --filter label=projecte=aurora-libros --format "table {{.Label \"component\"}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"'
alias aurora-aturar='docker stop $(docker ps -q --filter label=projecte=aurora-libros)'
alias aurora-arrencar='docker start $(docker ps -aq --filter label=projecte=aurora-libros)'I una versió amb salut i mida, per quan alguna cosa va malament:
docker ps -as --filter label=projecte=aurora-libros \
--format 'table {{.Names}}\t{{.Status}}\t{{.Size}}'NAMES STATUS SIZE
aurora-cache Up 23 minutes 0B (virtual 41.2MB)
aurora-db Up 23 minutes 3.14kB (virtual 278MB)Fixa't que la capa d'escriptura d'aurora-db ha crescut de 127 kB a 3,14 kB… un moment, ha baixat. El que passa és que el contenidor és nou: el vas recrear en afegir-li les etiquetes, i aquests 3,14 kB són gairebé exclusivament l'init.sql que vas copiar amb docker cp. Les dades dels vuit llibres no hi són, sinó al volum anònim del qual parlàvem. Un recordatori més que hi ha una peça del trencaclosques que encara no has col·locat.
Errors Habituals i Consells
- Executar
docker rm -f $(docker ps -aq)"per netejar". S'emporta tot el de la màquina, inclosos contenidors d'altres projectes i bases de dades de desenvolupament amb setmanes de dades. Filtra sempre perlabelo pername. - Confiar en
--filter name=com si fos una igualtat. És una subcadena:name=aurora-dbtambé trobaaurora-db-backup. Ancora amb^...$quan importi. - Llegir la columna
CREATEDcom a "arrencat fa". És la data de creació. Per al temps en marxa, miraSTATUSo{{.RunningFor}}. - Interpretar la mida
virtualcom a espai ocupat. Deu contenidors de la mateixa imatge comparteixen les seves capes: el disc real és la suma de les capes d'escriptura més una còpia de la imatge. - Fer servir
docker rm -fsobre una base de dades. És un SIGKILL sense gràcia. Primerdocker stop --time 30, desprésdocker rm. - Oblidar
-ven esborrar i acumular volums anònims orfes. Cada contenidor de PostgreSQL esborrat sense-vdeixa enrere el seu volum. Es localitzen ambdocker volume ls -f dangling=true(lliçó 03-06). - Copiar fitxers amb
docker cpa un contenidor sense privilegis i no entendre elpermission denied. El fitxer hi arriba com a root. Fes servir-a, o ajusta-ho després ambdocker exec -u root ... chown. - Construir imatges amb
docker commit. Funciona avui i et deixa sense explicació demà. El Dockerfile és la font de la veritat. - Consell: desa els teus formats preferits a
~/.docker/config.jsonambpsFormat. Undocker psllegible per defecte és un regal diari. - Consell: abans de qualsevol operació massiva, executa la versió que només llista. Mira la llista, i només llavors canvia
psperrm.
Exercicis
Exercici 1: munta el teu propi tauler de control
Crea cinc contenidors de prova amb alpine:3.20 i sleep 300, etiquetats així: dos amb projecte=aurora-libros i entorn=local, dos amb projecte=aurora-libros i entorn=proves, i un amb projecte=altre-client. Després escriu una única comanda docker ps que mostri només els d'Aurora Libros en entorn de proves, en una taula amb les columnes nom, entorn i temps en marxa. Finalment, atura i esborra en una sola comanda exclusivament els d'altre-client, deixant la resta intacta, i demostra amb una altra comanda que els quatre d'Aurora Libros continuen vius.
Exercici 2: investiga què escriu un contenidor (i on no ho escriu)
Arrenca un contenidor de redis:7-alpine anomenat diff-redis. Abans de tocar res, executa docker diff i anota el resultat. Després escriu 100 claus amb redis-cli, força un desament a disc amb redis-cli SAVE, i torna a executar docker diff. Respon:
- Apareix el fitxer de dades de Redis al
docker diff? I a la columnaSIZEdedocker ps -s? - Esbrina amb
docker inspect --format '{{json .Mounts}}'on és realment aquest fitxer. - Copia'l al host amb
docker cpi comprova'n la mida ambls -lh. - Esborra el contenidor amb
docker rm -f(sense-v) i explica què ha passat exactament amb aquelles 100 claus. S'han perdut? On són?
Exercici 3: rescat i neteja segura
Simula el final d'una jornada de treball caòtica:
- Crea sis contenidors que acabin immediatament: tres amb codi 0 (
alpine:3.20 true) i tres amb codi 1 (alpine:3.20 sh -c 'exit 1'), tots amb l'etiquetaprojecte=proves-neteja. - Escriu una comanda que llisti només els que van fallar, amb el seu nom i el seu estat.
- D'un dels fallits, extreu amb
docker cpel fitxer/etc/os-releaseal host abans d'esborrar-lo. - Esborra en una sola comanda només els que van fallar, deixant els tres correctes.
- Finalment, neteja la resta amb
docker container pruneacotat a l'etiqueta, i verifica que niaurora-dbniaurora-cacheno s'han vist afectats.
Solucions
Solució a l'exercici 1
for n in 1 2; do
docker run -d --name prova-local-$n \
--label projecte=aurora-libros --label entorn=local \
alpine:3.20 sleep 300
done
for n in 1 2; do
docker run -d --name prova-proves-$n \
--label projecte=aurora-libros --label entorn=proves \
alpine:3.20 sleep 300
done
docker run -d --name prova-altre --label projecte=altre-client alpine:3.20 sleep 300La comanda del tauler, amb dos filtres combinats amb I lògic:
docker ps --filter label=projecte=aurora-libros --filter label=entorn=proves \
--format 'table {{.Names}}\t{{.Label "entorn"}}\t{{.RunningFor}}'Els d'entorn=local no hi apareixen: compleixen el primer filtre però no el segon, i tots dos s'han de complir.
Esborrat quirúrgic d'altre-client:
# Primer MIRAR
docker ps -a --filter label=projecte=altre-client --format "{{.Names}}"
# Després ACTUAR
docker rm -f $(docker ps -aq --filter label=projecte=altre-client)
# I COMPROVAR
docker ps --filter label=projecte=aurora-libros --format "{{.Names}}" | wc -lEls quatre d'Aurora Libros continuen drets. La seqüència mirar → actuar → comprovar és la que converteix una comanda perillosa en una operació rutinària.
Solució a l'exercici 2
Pràcticament res: Redis acabat d'arrencar només escriu el seu fitxer de PID. Ara, càrrega i desament:
docker exec diff-redis sh -c 'for i in $(seq 1 100); do redis-cli SET llibre:$i "titol-$i" > /dev/null; done'
docker exec diff-redis redis-cli DBSIZE
docker exec diff-redis redis-cli SAVE
docker exec diff-redis ls -lh /data
docker diff diff-redis
docker ps -s --filter name=diff-redis --format "{{.Names}}: {{.Size}}"(integer) 100
OK
-rw-r--r-- 1 redis redis 3.4K Aug 4 20:41 dump.rdb
C /run
A /run/redis_6379.pid
diff-redis: 0B (virtual 41.2MB)1. Aquí hi ha la sorpresa de l'exercici: dump.rdb existeix (l'acabes de llistar amb ls -lh, 3,4 kB) però no apareix al docker diff, i la capa d'escriptura continua mesurant 0 B. Les dues eines estan d'acord entre elles i totes dues diuen la veritat: aquest fitxer no és a la capa d'escriptura del contenidor.
2. L'explicació és als muntatges:
[
{
"Type": "volume",
"Name": "b41f7c9e2a8d05f31c6e8b4a2d97f0c5e3a1b8d6f4c2e0a9b7d5f3c1e8a6b4d2",
"Source": "/var/lib/docker/volumes/b41f7c9e2a8d.../_data",
"Destination": "/data",
"Driver": "local",
"RW": true
}
]La imatge oficial de Redis declara VOLUME /data, així que Docker va crear un volum anònim —aquest nom que sembla un hash és exactament això: un volum sense nom— i el va muntar a /data. Tot el que Redis hi escriu va al volum, no a la capa d'escriptura, i per això docker diff no ho veu.
3.
Successfully copied 5.63kB to /tmp/dump-aurora.rdb
-rw-r--r-- 1 junior junior 3.4K Aug 4 20:42 /tmp/dump-aurora.rdbdocker cp sí que llegeix a través dels muntatges: per a ell, /data/dump.rdb és simplement una ruta del sistema de fitxers del contenidor. Els 3,4 kB coincideixen amb l'ls de dins; els 5,63 kB que informa Docker són la mida del flux tar amb què es fa la còpia, amb les seves capçaleres i el seu farciment a blocs.
4.
La resposta correcta és més interessant que un simple "s'han perdut":
- Les claus que eren en memòria van morir amb el procés, com a l'exercici de la lliçó anterior.
- Però el
dump.rdbamb les 100 claus continua existint, en un volum que ara està orfe: sense contenidor que el faci servir, amb un nom que ningú no recorda i ocupant disc indefinidament. Com que vas fer servirdocker rm -fsense-v, el volum no es va esborrar. - Si demà arrenques un altre
redis:7-alpine, Docker crearà un volum anònim nou i buit: no reutilitzarà l'anterior. Des del punt de vista pràctic, les dades estan perdudes encara que els bytes continuïn al teu disc.
Això és exactament el que li passa avui a aurora-db amb els vuit llibres que acabes de carregar, i és el problema que resol la lliçó 03-06 posant-li al volum un nom.
Solució a l'exercici 3
for n in 1 2 3; do
docker run --name ok-$n --label projecte=proves-neteja alpine:3.20 true
docker run --name fallada-$n --label projecte=proves-neteja alpine:3.20 sh -c 'exit 1'
done2. Llistar només els que van fallar, combinant status i exited:
docker ps -a --filter label=projecte=proves-neteja --filter exited=1 \
--format "table {{.Names}}\t{{.Status}}"NAMES STATUS
fallada-3 Exited (1) 6 seconds ago
fallada-2 Exited (1) 7 seconds ago
fallada-1 Exited (1) 8 seconds agoEl filtre exited=1 és el que fa la feina fina: distingeix "va acabar" de "va acabar malament", cosa que status=exited per si sol no pot.
3. Rescatar un fitxer d'un contenidor aturat:
docker cp fallada-1:/etc/os-release /tmp/os-release-fallada1.txt
head -2 /tmp/os-release-fallada1.txtDetall important: docker cp funciona amb el contenidor aturat. No cal arrencar-lo, i això el converteix en l'eina ideal per fer autòpsies de contenidors que ja no s'aixequen.
4. Esborrat selectiu dels fallits:
docker rm $(docker ps -aq --filter label=projecte=proves-neteja --filter exited=1)
docker ps -a --filter label=projecte=proves-neteja --format "{{.Names}} {{.Status}}"2f8c1a9e4b73
7d1e5b2c8f04
9a3f7c1e5d28
ok-3 Exited (0) 1 minute ago
ok-2 Exited (0) 1 minute ago
ok-1 Exited (0) 1 minute agoEls tres correctes continuen allà. No va caldre -f perquè ja estaven aturats.
5. Neteja final acotada i verificació:
docker container prune -f --filter "label=projecte=proves-neteja"
docker ps -a --filter label=projecte=aurora-libros \
--format 'table {{.Names}}\t{{.Status}}'Deleted Containers:
1c7e9a3f5b28...
4b8d2f6a1c93...
6e0a4c8f2b17...
Total reclaimed space: 0B
NAMES STATUS
aurora-cache Up 41 minutes
aurora-db Up 41 minutesaurora-db i aurora-cache intactes, perquè el --filter label= va acotar el prune a l'etiqueta correcta. Compara mentalment amb el que hauria passat amb un docker container prune -f sense més: els tres ok-* haurien caigut igual, però també qualsevol contenidor aturat de qualsevol altre projecte de la teva màquina. Les etiquetes no són burocràcia: són el mecanisme que fa que la neteja sigui selectiva en comptes d'indiscriminada.
Conclusió
Ja no mires docker ps: el llegeixes. Saps què diu cadascuna de les seves set columnes i, sobretot, què no diu —que CREATED no és l'hora d'arrencada, que IMAGE pot haver quedat obsoleta si l'etiqueta es va moure, i que el número virtual de -s no és espai ocupat sinó espai vist—. Saps filtrar per estat, nom, imatge, etiqueta, codi de sortida i salut, combinant filtres amb I i amb O, i saps donar forma a la sortida amb plantilles Go fins a convertir-la en un tauler de control d'Aurora Libros que cap en un àlies.
Has après a compondre comandes amb -q i, més important, a fer-ho amb xarxa: mirar → actuar → comprovar, filtrant sempre per etiqueta perquè un esborrat massiu no s'emporti mai el que no era seu. Coneixes la diferència entre docker rm i docker rm -f —que no és stop + rm, sinó un SIGKILL sense gràcia—, saps què es destrueix i què sobreviu en esborrar un contenidor, i fas servir docker container prune acotat amb until i label en comptes de a pèl. Has etiquetat la flota amb projecte, component i entorn, que és exactament el mecanisme que Docker Compose automatitzarà per tu al mòdul 4.
Amb docker cp mous fitxers en els dos sentits, fins i tot amb el contenidor aturat, i això t'ha servit per a una cosa memorable: els vuit llibres d'Aurora Libros estan carregats a PostgreSQL, amb la seva taula, el seu índex i el seu INSERT 0 8. Amb docker diff saps veure la capa d'escriptura convertida en llista de fitxers —A, C i D— i has descobert la peça que falta: el directori de dades de PostgreSQL no apareix al diff, perquè no és a la capa d'escriptura, sinó en un volum anònim que la imatge declara i que ningú no controla. I saps per què docker commit no serveix per construir imatges, encara que sigui perfecte per congelar l'escena d'un crim abans de netejar-la.
Saps mirar la flota quan tot va bé. Falta l'altra cara. A la lliçó següent, Inspecció i Depuració de Contenidors, t'enfrontaràs als contenidors que no funcionen i no diuen per què: llegiràs docker logs a fons amb els seus filtres de temps i la seva regla d'or sobre stdout, entraràs amb docker exec fins i tot en imatges mínimes que no tenen ni ping —amb contenidors efímers que en comparteixen els namespaces—, espremeràs el JSON de docker inspect amb plantilles i jq, i vigilaràs en directe amb docker top, docker stats i docker events. I aplicaràs tot això a tres avaries reals d'Aurora Libros, entre elles la que fa dues lliçons que espera: per què aurora-api no troba aurora-db encara que tots dos estiguin corrent a la mateixa màquina.
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
