Quan vas executar docker run hello-world a la lliçó anterior, el mateix missatge del contenidor et va resumir el que havia passat: el client va contactar amb el daemon, el daemon va descarregar una imatge del registre, va crear un contenidor a partir d'ella i et va retornar la seva sortida. Aquesta frase amaga una arquitectura completa, i entendre-la és el que separa qui memoritza comandes de qui sap diagnosticar problemes. En aquesta lliçó obriràs la caixa: descobriràs que docker no executa contenidors (només els demana), qui els executa realment, quin paper hi juguen containerd i runc, què és aquest socket del qual tant parlem i per què el daemon és el veritable amo de totes les teves imatges, contenidors, volums i xarxes. Acabaràs interpretant la sortida real de docker info i docker system df amb ulls nous.

Contingut

  1. Docker és client-servidor, no un programa
  2. El client docker
  3. El daemon dockerd
  4. L'API REST i el socket /var/run/docker.sock
  5. El flux complet d'un docker run
  6. containerd i runc: per què hi ha tres capes
  7. Els objectes que gestiona el daemon
  8. Els registres i el seu paper
  9. Demostració pràctica: docker info i docker system df

  1. Docker és client-servidor, no un programa

El primer malentès que cal desfer: quan escrius docker run, aquesta comanda no crea cap contenidor. L'única cosa que fa és traduir la teva ordre a una petició HTTP i enviar-la a un altre procés, que és el que fa la feina de debò.

Docker segueix una arquitectura client-servidor amb tres actors:

Actor Què és On viu
Client (docker) Un programa de línia de comandes que tradueix les teves ordres a crides d'API El teu terminal
Daemon (dockerd) Un servei de llarga durada que construeix, executa i gestiona tot Normalment la mateixa màquina; pot ser remota
Registre Un servei que emmagatzema i distribueix imatges Internet (Docker Hub) o la teva xarxa

Les conseqüències d'aquest disseny són molt pràctiques:

  • El client pot estar en una màquina diferent del daemon. Pots gestionar un servidor remot des del teu portàtil amb la mateixa comanda docker.
  • Hi pot haver molts clients contra un mateix daemon. El teu terminal, el teu IDE i una eina de CI poden parlar amb el mateix motor alhora.
  • Si el daemon està aturat, el client no pot fer res. D'aquí el famós Cannot connect to the Docker daemon.
  • L'estat viu al daemon, no al teu terminal. Tancar el terminal no atura els teus contenidors.

  1. El client docker

El client és sorprenentment ximple, i això és bo. Les seves responsabilitats són:

  1. Analitzar el que escrius (docker run -d --name web nginx).
  2. Convertir-ho en una o diverses crides a l'API REST del daemon.
  3. Mostrar-te la resposta amb format llegible.

Res més. No sap crear contenidors, ni descomprimir imatges, ni parlar amb el nucli.

El client decideix amb quin daemon parla mitjançant els anomenats contextos. Els pots veure així:

docker context ls
NAME       DESCRIPTION                               DOCKER ENDPOINT               ERROR
default *  Current DOCKER_HOST based configuration   unix:///var/run/docker.sock

Lectura: hi ha un únic context, default, marcat com a actiu amb l'asterisc, i apunta al socket Unix local. Si tinguessis un servidor remot configurat, hi veuries una altra fila amb un DOCKER ENDPOINT del tipus ssh://usuari@servidor.

També pots forçar el destí amb la variable d'entorn DOCKER_HOST:

DOCKER_HOST=ssh://joan@servidor-produccio docker ps

Aquesta comanda llista els contenidors del servidor remot, no els teus. El client és exactament el mateix binari; només canvia amb qui parla. És una demostració perfecta que el client no executa res.

  1. El daemon dockerd

dockerd és el procés que fa la feina. Corre com a servei del sistema (a Linux, gestionat per systemd) amb privilegis de root, perquè necessita manipular el nucli: crear espais de noms, configurar interfícies de xarxa virtuals, muntar sistemes de fitxers.

El pots veure amb les eines normals del sistema:

systemctl status docker
ps -ef | grep dockerd

La primera línia et mostra l'estat del servei (active (running)); la segona, el procés real i els seus arguments. Hi veuràs alguna cosa com /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock, on -H fd:// indica que escolta al socket que li passa systemd i --containerd= assenyala amb quin containerd parla (ho veurem a l'apartat 6).

Les seves responsabilitats:

  • Exposar l'API REST i atendre els clients.
  • Gestionar el cicle de vida d'imatges, contenidors, volums i xarxes.
  • Descarregar i pujar imatges des dels registres i cap a ells.
  • Construir imatges (delegant en BuildKit, tema del mòdul 2 i de la lliçó 05-05).
  • Configurar la xarxa virtual dels contenidors.
  • Delegar l'execució real en containerd.

Un detall important: si dockerd es reinicia, els teus contenidors no han de morir necessàriament. Gràcies a la separació amb containerd que veuràs de seguida, els contenidors en execució poden sobreviure a un reinici del daemon.

  1. L'API REST i el socket /var/run/docker.sock

Tota la comunicació entre el client i el daemon és una API REST sobre HTTP. El que crida l'atenció és que, per defecte, aquest HTTP no viatja per la xarxa: viatja per un socket Unix, un fitxer especial del sistema de fitxers:

ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 ago  4 09:12 /var/run/docker.sock

Llegeix-ho amb atenció, perquè explica coses de la lliçó anterior:

  • La s inicial indica que és un socket, no un fitxer normal.
  • El propietari és root i el grup és docker.
  • Els permisos rw-rw---- signifiquen: root pot llegir i escriure, el grup docker també, i ningú més.

Aquí ho tens, en una línia, per què necessitaves sudo o pertànyer al grup docker. I també per què pertànyer al grup docker equival a ser root: qui pot escriure en aquest socket pot demanar al daemon (que és root) el que vulgui.

Que l'API sigui HTTP té una conseqüència divertida: pots parlar amb Docker sense fer servir el client. Amb curl:

curl --unix-socket /var/run/docker.sock http://localhost/version
{"Platform":{"Name":"Docker Engine - Community"},"Version":"28.1.1","ApiVersion":"1.49","Os":"linux","Arch":"amd64"}

Què acabes de fer: --unix-socket diu a curl que en lloc d'obrir una connexió TCP faci servir aquest fitxer socket; http://localhost/version és la ruta de l'endpoint (l'amfitrió és irrellevant, només cal per formar una URL vàlida). La resposta és JSON cru: exactament el mateix que docker version et mostra bonic.

Un altre exemple, llistant contenidors:

curl --unix-socket /var/run/docker.sock http://localhost/v1.49/containers/json

Retorna un array JSON amb els contenidors en execució: l'equivalent exacte de docker ps. Això no és cap truc de festa: és com funcionen per dins les eines gràfiques, els plugins d'IDE i els sistemes de monitoratge.

Advertiment de seguretat. Muntar /var/run/docker.sock dins d'un contenidor és una pràctica que veuràs en tutorials (eines de CI, taulers). Equival a donar-li root sobre l'amfitrió a aquest contenidor. Es tracta amb detall a la lliçó 05-03.

El daemon pot a més escoltar en TCP (-H tcp://0.0.0.0:2376), imprescindible per a l'accés remot, però mai sense TLS i autenticació: un daemon exposat sense protegir a Internet es compromet en minuts.

  1. El flux complet d'un docker run

Ara sí, el recorregut complet de l'ordre més habitual del curs:

docker run -d --name aurora-web-demo -p 8080:80 nginx:alpine
sequenceDiagram
    participant U as Tu (terminal)
    participant C as Client docker
    participant D as Daemon dockerd
    participant R as Registre (Docker Hub)
    participant CD as containerd
    participant RC as runc
    participant K as Nucli Linux

    U->>C: docker run -d -p 8080:80 nginx:alpine
    C->>D: POST /images/create (si falta la imatge)
    D->>D: Hi ha nginx:alpine en local?
    alt No hi és
        D->>R: GET manifest + capes
        R-->>D: Manifest i capes (blobs)
        D->>D: Descomprimeix i desa les capes
    end
    C->>D: POST /containers/create
    D->>D: Prepara sistema de fitxers i config de xarxa
    C->>D: POST /containers/{id}/start
    D->>CD: Crear i arrencar contenidor
    CD->>RC: Crear procés aïllat segons spec OCI
    RC->>K: namespaces + cgroups + muntatges
    K-->>RC: Procés en execució
    RC-->>CD: Llest (runc acaba)
    CD-->>D: ID del contenidor i estat
    D-->>C: ID del contenidor
    C-->>U: 3f2a9c1b7e4d...

Pas a pas, en paraules:

  1. Tu escrius la comanda. El client l'analitza i valida les opcions.
  2. El client crida l'API. Tradueix la teva ordre a peticions HTTP contra el socket.
  3. El daemon busca la imatge en local. Si nginx:alpine ja està descarregada, salta al pas 5.
  4. Si falta, el daemon contacta amb el registre. Demana primer el manifest (la llista de capes que componen la imatge) i després descarrega les capes que no tingui ja. Són aquestes descàrregues les que veus com a Pull complete.
  5. El daemon crea el contenidor. Prepara el seu sistema de fitxers apilant les capes de la imatge i afegint-hi a sobre una capa d'escriptura, reserva el nom aurora-web-demo, i configura la xarxa virtual i la regla de mapatge del port 8080 de l'amfitrió al 80 del contenidor.
  6. El daemon demana a containerd que l'arrenqui.
  7. containerd invoca runc, que és qui realment diu al nucli: crea aquests espais de noms, aplica aquests límits de recursos, munta aquest sistema de fitxers i llança aquest procés.
  8. runc acaba i desapareix. La seva feina era arrencar el procés, no supervisar-lo.
  9. El daemon retorna l'ID al client, que te l'imprimeix.

Que runc desaparegui després d'arrencar el contenidor és la raó per la qual Docker pot actualitzar-se o reiniciar-se sense matar contenidors: el procés del contenidor ja no en penja.

  1. containerd i runc: per què hi ha tres capes

A primera vista, tres components per arrencar un procés sembla exagerat. La raó és històrica i estratègica.

Els primers anys, Docker era un binari monolític que ho feia tot. A mesura que els contenidors es van convertir en infraestructura crítica, la indústria va demanar estàndards per no dependre d'un únic proveïdor. D'aquí va néixer l'OCI (Open Container Initiative), que va publicar dues especificacions clau:

  • OCI Image Spec: com s'estructura una imatge (capes, manifest, configuració).
  • OCI Runtime Spec: com es descriu i s'arrenca un contenidor a partir d'un sistema de fitxers i un fitxer de configuració JSON.

Docker es va trossejar per encaixar en aquests estàndards:

Component Nivell Responsabilitat
dockerd Alt API REST, construcció d'imatges, xarxes, volums, orquestració local
containerd Mitjà Gestió del cicle de vida de contenidors, emmagatzematge d'imatges, transferència des de registres, supervisió
runc Baix Crear un contenidor a partir d'una spec OCI parlant amb el nucli, i sortir

Mira-t'ho com una cadena de delegació, cada baula més específica i més simple que l'anterior:

flowchart TB
    CLI["Client docker"] -->|API REST| DAEMON["dockerd<br/>(alt nivell)"]
    DAEMON -->|gRPC| CTRD["containerd<br/>(nivell mitjà, estàndard de l'ecosistema)"]
    CTRD -->|executa| SHIM["containerd-shim<br/>(supervisa el contenidor)"]
    SHIM -->|invoca un cop| RUNC["runc<br/>(baix nivell, OCI Runtime)"]
    RUNC -->|syscalls| KERNEL["Nucli Linux<br/>namespaces · cgroups · capabilities"]
    KERNEL --> PROC["Procés del contenidor"]
    SHIM -.supervisa.-> PROC

Aquest containerd-shim intermedi és la peça que explica el "reinici sense morts": hi ha un shim per contenidor que es queda viu supervisant-lo, en recull el codi de sortida i manté oberts els seus fluxos d'entrada/sortida, de manera que ni dockerd ni runc necessiten continuar presents.

Per què t'importa això com a usuari?

  • Perquè containerd és avui un estàndard de l'ecosistema, i altres plataformes el fan servir directament (Kubernetes, per exemple, parla amb containerd sense passar per Docker). Ho veuràs al mòdul 6.
  • Perquè explica que existeixin alternatives compatibles a Docker que executen exactament les mateixes imatges (tema de la lliçó 07-05).
  • Perquè quan llegeixis un error que esmenti containerd o runc, sabràs a quin nivell està fallant alguna cosa.

El que passa exactament a la fletxa final —què són els namespaces, els cgroups i com s'apilen les capes del sistema de fitxers— és el contingut de la lliçó 05-07. Aquí ens quedem al mapa.

  1. Els objectes que gestiona el daemon

El daemon manté quatre tipus d'objecte. Tot el que faràs al curs és crear, llistar, inspeccionar i esborrar objectes d'aquests quatre tipus, i la CLI moderna està organitzada literalment així (ho veuràs a la lliçó 01-04).

Objecte Què és Comanda arrel On s'hi aprofundeix
Imatges Plantilles immutables de només lectura docker image Lliçó 01-05 i mòdul 2
Contenidors Instàncies en execució d'una imatge docker container Lliçó 01-06 i mòdul 3
Volums Emmagatzematge persistent independent del cicle de vida del contenidor docker volume Lliçó 03-06
Xarxes Xarxes virtuals que connecten contenidors entre si i amb l'exterior docker network Lliçó 03-05

Tots ells es materialitzen al disc sota el directori de dades del daemon, normalment /var/lib/docker:

sudo ls /var/lib/docker
buildkit  containers  image  network  overlay2  plugins  runtimes  swarm  tmp  volumes

Què és cada cosa rellevant:

  • overlay2: les capes de les imatges i les capes d'escriptura dels contenidors. És el que més ocupa amb diferència.
  • image: les metadades que relacionen imatges amb les seves capes.
  • containers: configuració i registres de cada contenidor.
  • volumes: les dades dels volums.
  • network: la configuració de les xarxes virtuals.
  • buildkit: la memòria cau de construcció d'imatges.

Regla d'or: no toquis mai a mà res de /var/lib/docker. El daemon hi manté bases de dades internes d'estat; editar o esborrar fitxers directament és la manera més ràpida de corrompre la instal·lació. Tot es gestiona amb comandes.

  1. Els registres i el seu paper

Un registre és un servei que emmagatzema i distribueix imatges. És la tercera pota de l'arquitectura i la que dona a Docker la seva capacitat de distribució.

El registre per defecte és Docker Hub (docker.io). Quan escrius docker pull nginx:alpine, el client completa silenciosament el nom:

nginx:alpine  →  docker.io/library/nginx:alpine

On docker.io és el registre, library és l'espai de noms de les imatges oficials i nginx el repositori. Per això a la sortida de hello-world vas veure Pulling from library/hello-world.

Per fer servir un altre registre n'hi ha prou d'anomenar-lo explícitament:

docker pull ghcr.io/aurora-libros/aurora-api:1.0.0
docker pull registry.intern.auroralibros.local:5000/aurora-api:1.0.0
  • El primer descarrega del GitHub Container Registry.
  • El segon, d'un registre privat autoallotjat a la xarxa de l'empresa, que escolta al port 5000.

Tipus habituals de registre:

Tipus Exemples Quan es fa servir
Públic gestionat Docker Hub, GitHub Container Registry, Quay Imatges base i projectes oberts
Privat gestionat al núvol Amazon ECR, Google Artifact Registry, Azure ACR Imatges d'empresa desplegades en aquell núvol
Privat autoallotjat Harbor, el registre oficial registry:2, Nexus Control total, xarxes aïllades, compliment normatiu

El paper del registre a l'arquitectura és el de magatzem i punt d'intercanvi: el daemon puja (push) i baixa (pull) imatges, però no el necessita per executar el que ja té descarregat. Un servidor sense connexió a Internet pot aixecar contenidors perfectament si les seves imatges ja són en local.

L'autenticació (docker login), la publicació i l'organització de repositoris es tracten al mòdul 2, especialment a les lliçons 02-01 i 02-06.

  1. Demostració pràctica: docker info i docker system df

Llegim l'arquitectura reflectida a la sortida real de dues comandes.

docker info

docker info
Client: Docker Engine - Community
 Version:    28.1.1
 Context:    default
 Plugins:
  buildx: Docker Buildx (Docker Inc.)  v0.23.0
  compose: Docker Compose (Docker Inc.) v2.35.1

Server:
 Containers: 4
  Running: 2
  Paused: 0
  Stopped: 2
 Images: 7
 Server Version: 28.1.1
 Storage Driver: overlay2
  Backing Filesystem: extfs
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 containerd version: 05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc version: v1.2.5-0-g59923ef
 Kernel Version: 6.8.0-52-generic
 Operating System: Ubuntu 24.04.2 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 15.35GiB
 Docker Root Dir: /var/lib/docker
 Registry: https://index.docker.io/v1/
 Live Restore Enabled: false

Ara que coneixes l'arquitectura, cada bloc té sentit:

Camp Què t'indica
Blocs Client: / Server: La separació client-servidor en persona. Són dues entitats diferents
Context: default Amb quin daemon està parlant el client
Containers / Running / Stopped L'inventari d'objectes "contenidor" que custodia el daemon. Fixa't que n'hi ha 2 d'aturats: existeixen i ocupen disc
Images: 7 Els objectes "imatge" emmagatzemats
Storage Driver: overlay2 Com apila les capes d'imatge (lliçó 01-05)
Logging Driver: json-file On van els registres dels contenidors (lliçó 05-06)
Cgroup Driver / Version Com s'apliquen els límits de recursos (lliçons 03-07 i 05-07)
Network: bridge host ipvlan... Els drivers de xarxa disponibles (lliçons 03-05 i 05-01)
containerd version / runc version Les dues capes inferiors de l'apartat 6, llistades explícitament
Kernel Version El nucli de l'amfitrió, que és el que faran servir els teus contenidors
Docker Root Dir El directori de l'apartat 7
Registry: https://index.docker.io/v1/ El registre per defecte de l'apartat 8
Live Restore Enabled Si està en true, els contenidors sobreviuen a un reinici del daemon

A Windows o macOS, fixa't que Operating System i Kernel Version no són els del teu equip, sinó els de la màquina virtual Linux de Docker Desktop. És la demostració més clara del que es va explicar a la lliçó 01-02.

docker system df

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          7         2         1.842GB   1.376GB (74%)
Containers      4         2         12.4MB    8.2MB (66%)
Local Volumes   3         1         248.6MB   102.3MB (41%)
Build Cache     18        0         421.7MB   421.7MB (100%)

Aquesta comanda respon a "en què se me'n va el disc?". Columna a columna:

  • TYPE: els tipus d'objecte de l'apartat 7, més la memòria cau de construcció.
  • TOTAL: quants objectes hi ha d'aquest tipus.
  • ACTIVE: quants estan en ús. Una imatge està activa si algun contenidor (encara que estigui aturat) la fa servir; un volum, si està muntat per algun contenidor.
  • SIZE: espai total ocupat. Compte: a Images, aquest nombre té en compte que les capes compartides es compten una sola vegada (lliçó 01-05).
  • RECLAIMABLE: quant recuperaries netejant el que no es fa servir. A l'exemple, 1,376 GB d'imatges que cap contenidor no referencia.

Per al detall per objecte:

docker system df -v

Hi afegeix taules desglossades: cada imatge amb la seva mida i quants contenidors la fan servir, cada contenidor amb la mida de la seva capa d'escriptura, cada volum amb els seus enllaços. És l'eina per localitzar el culpable concret d'un disc ple.

La neteja (docker system prune) la veuràs a la lliçó 01-04.

Errors Habituals i Consells

  • Creure que docker "és" Docker. La comanda és només un client. Si t'acostumes a pensar "jo demano, el daemon fa", entendràs per què el daemon pot ser en una altra màquina, per què tancar el terminal no atura res i per què l'estat no és on escrius.
  • Confondre "no trobo el contenidor" amb "no existeix". Si tens diversos contextos o un DOCKER_HOST posat a l'entorn, pots estar consultant un altre daemon. Verifica-ho amb docker context ls i echo $DOCKER_HOST.
  • Exposar el daemon per TCP sense TLS. Obrir -H tcp://0.0.0.0:2375 és lliurar la màquina. Existeixen botnets que rastregen aquest port contínuament. Si necessites accés remot, fes servir el context per SSH (docker context create --docker host=ssh://...), que és simple i segur.
  • Muntar /var/run/docker.sock dins d'un contenidor a la lleugera. És una escalada a root de l'amfitrió. De vegades cal, però ha de ser una decisió conscient (lliçó 05-03).
  • Tocar /var/lib/docker a mà. Esborrar directoris allà per "alliberar espai" corromp l'estat del daemon. Fes servir sempre les comandes de la CLI.
  • Consell: docker info és el teu primer diagnòstic. Davant de qualsevol comportament estrany, mira-hi: versió, driver d'emmagatzematge, cgroups, arquitectura i espai. Molts problemes "misteriosos" s'expliquen amb una línia d'aquesta sortida.
  • Consell: recorda la cadena de delegació. dockerd → containerd → shim → runc → nucli. Amb aquest esquema al cap, els missatges d'error de baix nivell deixen de ser soroll.

Exercicis

Exercici 1: parla amb l'API sense fer servir el client

Sense executar cap comanda docker (llevat de per comparar al final), aconsegueix mitjançant curl sobre el socket Unix: (a) la versió del daemon, (b) el nombre de contenidors en execució, i (c) la llista d'imatges locals. Després, compara cada resultat amb la seva comanda docker equivalent i explica quina relació hi ha entre totes dues.

Exercici 2: segueix el rastre de les capes

Executa aquestes comandes i respon a les preguntes:

docker system df
docker pull nginx:alpine
docker system df

(a) Quines xifres canvien i per què? (b) Quants objectes de tipus imatge hi ha ara actius i quants en total? (c) Si el RECLAIMABLE d'imatges és alt, què significa exactament això en termes de l'arquitectura que has estudiat?

Exercici 3: dibuixa la fallada

Per a cadascun d'aquests tres símptomes, indica en quin punt exacte de la cadena client → API/socket → daemon → registre → containerd → runc → nucli és el problema, i què comprovaries:

  1. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
  2. Error response from daemon: pull access denied for aurora-api, repository does not exist or may require 'docker login'
  3. docker: Error response from daemon: driver failed programming external connectivity on endpoint aurora-web-demo: Bind for 0.0.0.0:8080 failed: port is already allocated.

Solucions

Solució a l'exercici 1

# (a) versió del daemon
curl -s --unix-socket /var/run/docker.sock http://localhost/version

# (b) contenidors en execució (compte d'elements de l'array JSON)
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.49/containers/json | grep -o '"Id"' | wc -l

# (c) imatges locals
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.49/images/json

Comentaris:

  • -s silencia la barra de progrés de curl per deixar només el JSON.
  • --unix-socket és el que ho fa possible tot: en lloc d'una connexió TCP, curl escriu HTTP directament al fitxer socket. L'http://localhost és només un farciment sintàctic per formar una URL vàlida; el nom d'amfitrió s'ignora.
  • /v1.49/ és la versió de l'API; la pots ometre i el daemon farà servir la més recent que suporti. Si la teva versió difereix, mira-la a la sortida de docker version (camp API version).
  • A (b), el grep -o '"Id"' | wc -l compta quants objectes porta l'array. Amb jq instal·lat seria més net: | jq 'length'.

Els equivalents són docker version, docker ps i docker image ls. La relació és directa: el client docker fa exactament aquestes mateixes crides HTTP i es limita a formatar la resposta en taules llegibles. Comprovar-ho de primera mà és la millor manera d'interioritzar que el client no executa res.

Solució a l'exercici 2

(a) Canvien dues coses a la fila Images: el TOTAL puja en 1 (hi ha una imatge més) i el SIZE augmenta, però normalment menys que la mida anunciada de la imatge, perquè les capes que ja tinguessis d'altres imatges basades en Alpine no es descarreguen ni es compten dues vegades. A més, el RECLAIMABLE puja en la mida de la nova imatge, perquè acabes de descarregar-la i encara cap contenidor no la fa servir.

(b) TOTAL és el nombre d'imatges emmagatzemades; ACTIVE compta només les referenciades per algun contenidor (encara que estigui aturat). L'acabada de descarregar suma al total però no a les actives.

(c) Un RECLAIMABLE alt significa que el daemon està custodiant a /var/lib/docker capes d'imatges que cap contenidor no referencia. No fan mal més enllà del disc que ocupen, i serveixen de memòria cau: si tornes a fer servir aquesta imatge, no cal descarregar-la. S'alliberen amb docker system prune -a, que veuràs a la lliçó 01-04.

Solució a l'exercici 3

  1. Fallada entre el client i el socket/daemon. El client no aconsegueix ni tan sols establir la conversa. Dues causes possibles: el daemon està aturat (comprova-ho amb systemctl status docker; a Windows/macOS, que Docker Desktop estigui iniciat) o el teu context apunta a un endpoint que no respon (comprova docker context ls i echo $DOCKER_HOST). Compte amb la diferència respecte a permission denied: això seria un problema de permisos sobre el socket, no de connexió.

  2. Fallada entre el daemon i el registre. El missatge comença per Error response from daemon, així que el client va arribar al daemon sense problema; va ser el daemon qui no va poder obtenir la imatge. Comprovaries: que el nom i l'etiqueta siguin correctes, que el repositori existeixi, si és privat (llavors falta docker login), i si el registre és intern, que sigui accessible des de la màquina.

  3. Fallada al daemon, a la fase de configuració de xarxa prèvia a l'arrencada. El contenidor ni tan sols ha arribat a containerd/runc: el daemon va intentar reservar el port 8080 de l'amfitrió i el sistema operatiu l'hi va negar perquè ja està ocupat. Comprovaries què l'ocupa (ss -tlnp | grep 8080, o docker ps per si és un altre contenidor teu) i, o bé alliberes aquest port, o publiques el contenidor en un altre (-p 8081:80).

Conclusió

Docker no és un programa: és un sistema client-servidor. El client docker només tradueix les teves ordres a crides d'una API REST que viatja pel socket /var/run/docker.sock —els permisos del qual expliquen, d'un cop d'ull, tant l'ús de sudo com el fet que el grup docker equivalgui a root—. A l'altra banda, el daemon dockerd fa la feina real i delega cap avall en containerd (cicle de vida i emmagatzematge) i runc (creació del procés aïllat segons l'especificació OCI), una separació en capes que existeix per respectar estàndards i que permet que l'ecosistema no depengui d'un únic producte.

El daemon custodia quatre tipus d'objecte —imatges, contenidors, volums i xarxes— a /var/lib/docker, i fa servir els registres només per intercanviar imatges, no per executar-les. Tot això està reflectit, literalment, a la sortida de docker info i docker system df, que ara ja saps llegir.

Amb el mapa mental complet, ja pots començar a donar ordres amb criteri. A la lliçó següent, Comandes Bàsiques de Docker, veuràs que la CLI està organitzada exactament segons aquests quatre objectes (docker <objecte> <acció>), aprendràs les comandes essencials sobre imatges, contenidors i sistema, i recorreràs una sessió completa comentada de principi a fi.

Docker: De Principiant a Avançat

Mòdul 1: Introducció a Docker

Mòdul 2: Treballant amb Imatges Docker

Mòdul 3: Contenidors Docker

Mòdul 4: Docker Compose

Mòdul 5: Conceptes Avançats de Docker

Mòdul 6: Docker en Producció

Mòdul 7: Ecosistema i Eines de Docker

© Copyright 2026. Tots els drets reservats