Docker resol construir i executar contenidors. Tota la resta —veure què passa sense bussejar dins de docker ps, saber per què una imatge pesa de més, detectar vulnerabilitats abans de publicar, muntar un registre d'imatges propi, provar contra una base de dades real— ho resol l'ecosistema que hi ha al voltant. Aquesta lliçó no és un catàleg: és l'equipament seleccionat amb criteri, i el criteri per seleccionar-lo tu.

Contingut

  1. Els tres nivells d'extensibilitat
  2. Construeix el teu propi docker aurora
  3. Plugins del daemon i extensions de l'escriptori
  4. Interfícies de gestió
  5. Inspecció i optimització d'imatges
  6. Seguretat
  7. Registres d'imatges propis
  8. Desenvolupament i proves
  9. Construcció sense Dockerfile
  10. Neteja i manteniment
  11. Xarxa i diagnòstic
  12. Criteris per adoptar una eina
  13. El kit mínim recomanat

  1. Els tres nivells d'extensibilitat

Nivell Mecanisme Abast Risc si falla
CLI Binari docker-<nom> al PATH o a ~/.docker/cli-plugins/ La teva terminal Baix: no arrenca la subcomanda
Daemon Plugins de volum, xarxa o logging (API de plugins) Tot l'host Alt: pot tombar contenidors
Escriptori Extensions de Docker Desktop (contenidor + UI) La teva màquina Mitjà: codi de tercers amb accés al daemon

La regla que se'n dedueix: experimenta lliurement al nivell de la CLI, sigues conservador al del daemon. Un plugin de logging mal escrit bloqueja l'arrencada de tots els contenidors de l'host.

  1. Construeix el teu propi docker aurora

El mecanisme dels plugins de CLI és sorprenentment simple: qualsevol executable anomenat docker-alguna-cosa a ~/.docker/cli-plugins/ es converteix en docker alguna-cosa. Així funcionen docker compose, docker buildx i docker scout. L'únic requisit formal és respondre a la subcomanda oculta docker-cli-plugin-metadata.

#!/usr/bin/env bash
# ~/.docker/cli-plugins/docker-aurora — dreceres de l'equip d'Aurora Libros
set -euo pipefail

if [ "${1:-}" = "docker-cli-plugin-metadata" ]; then
  cat <<'JSON'
{ "SchemaVersion": "0.1.0", "Vendor": "Aurora Libros S.L.",
  "Version": "1.0.0", "ShortDescription": "Dreceres de la plataforma Aurora" }
JSON
  exit 0
fi

shift                     # el primer argument sempre és "aurora"
case "${1:-ajuda}" in
  amunt)   docker compose -f compose.yaml -f compose.dev.yaml up -d --wait ;;
  avall)   docker compose down ;;
  logs)    docker compose logs -f --tail=100 "${2:-api}" ;;
  psql)    docker compose exec -it aurora-db psql -U aurora -d aurora_llibres ;;
  redis)   docker compose exec -it aurora-cache redis-cli ;;
  salut)   curl -fsS localhost:8080/salut/preparat | jq . ;;
  llibres) curl -fsS localhost:8080/llibres | jq -r '.llibres[] | "\(.id)  \(.titol)"' ;;
  reset)   docker compose down -v && docker compose up -d --wait ;;
  *) echo "Ús: docker aurora {amunt|avall|logs|psql|redis|salut|llibres|reset}" ;;
esac
chmod +x ~/.docker/cli-plugins/docker-aurora
docker aurora amunt
docker aurora llibres
# 1  El jardín de senderos que se bifurcan
# 2  Rayuela
# 3  Cien años de soledad
# ...
docker --help | grep aurora
#   aurora*  Dreceres de la plataforma Aurora (Aurora Libros S.L. 1.0.0)

Quaranta línies i l'equip sencer deixa de memoritzar comandes llargues. Desa'l al repositori amb un make install-plugin i formarà part de l'onboarding. L'asterisc a l'ajuda indica que és un plugin, no una comanda nativa.

  1. Plugins del daemon i extensions de l'escriptori

Els plugins del daemon amplien Docker per sota. S'instal·len amb docker plugin install i es gestionen per separat:

docker plugin install grafana/loki-docker-driver:latest --alias loki
docker plugin ls
docker run --log-driver=loki --log-opt loki-url="http://loki:3100/loki/api/v1/push" ...
Tipus Exemples Quan es justifica
Volum rexray, local-persist, NFS/CIFS Emmagatzematge en xarxa des de Compose
Xarxa weave, calico Xarxes multi-host fora de Swarm/K8s
Logging loki, fluentd, gelf Centralitzar logs sense sidecar (05-06)

L'avís seriós: un plugin de logging que es bloqueja pot impedir que els contenidors arrenquin, perquè el daemon espera que accepti el flux. Abans de posar-lo en producció, prova'l amb la destinació caiguda a propòsit i comprova que mode: non-blocking està configurat.

Les extensions de Docker Desktop són contenidors amb interfície que s'integren al panell. Còmodes i amb la mateixa precaució que qualsevol codi de tercers amb accés al socket del daemon: si controla el socket, controla l'host (05-03).

  1. Interfícies de gestió

Eina Tipus Forta en Fluixa en Llicència
lazydocker TUI a la terminal Veure logs, reiniciar, estadístiques sense teclejar Només local MIT
ctop TUI, tipus top Veure consum de la flota d'un cop d'ull Sense gestió avançada MIT
Portainer Web, servidor Equips, permisos, diversos hosts, Swarm/K8s Pesat; CE retallat davant de BE Zlib (CE)
Dockge Web, servidor Gestionar piles de Compose editant el YAML Només Compose, projecte jove MIT
Docker Desktop GUI local Integrat, builds amb temps Només escriptori, llicència Propietària
# lazydocker: zero instal·lació permanent
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock \
  -v ~/.config/lazydocker:/.config/jesseduffield/lazydocker \
  lazyteam/lazydocker

Amb la pila d'Aurora Libros aixecada, lazydocker et dona en una pantalla els quatre contenidors, els seus logs en viu i el seu consum, i permet reiniciar aurora-api amb una tecla. Per depurar en local és més ràpid que qualsevol GUI.

Portainer només es justifica quan hi ha diverses persones operant diversos hosts i calen permisos per usuari. Per a un servidor i un equip petit amb Compose, Dockge és més lleuger i no amaga el YAML: continues tenint els teus fitxers i els edites des del navegador.

Precaució comuna a totes: exposen el socket de Docker. Portainer o Dockge accessibles des d'Internet sense autenticació forta equivalen a regalar l'host.

  1. Inspecció i optimització d'imatges

Eina Què fa Quan fer-la servir
dive Recorre la imatge capa a capa i calcula el malbaratament Abans de donar per bona una imatge
slim (abans docker-slim) Executa l'app, observa què fa servir i descarta la resta Imatges heretades que no pots reescriure
container-diff Compara dues imatges: paquets, fitxers, mides Auditar què va canviar entre 2.0.0 i 2.1.0
docker history Mida per capa, sense instal·lar res Primer cop d'ull ràpid
dive ghcr.io/auroralibros/aurora-api:2.0.0
# Image Details: Total Image size: 104 MB
#                Potential wasted space: 1.8 MB
#                Image efficiency score: 98%

Aquell 98 % és el resultat de la feina de 05-04: la multietapa va deixar fora les dependències de compilació i no hi ha fitxers duplicats entre capes. dive en mode integració retorna un codi de sortida diferent de zero si el projecte baixa del llindar, i això encaixa directament al pipeline:

CI=true dive --ci --lowestEfficiency 0.95 ghcr.io/auroralibros/aurora-api:2.0.0
# container-diff: què va canviar realment entre dues versions
container-diff diff --type=apt --type=file --type=size \
  daemon://aurora-api:2.0.0 daemon://aurora-api:2.1.0

Sobre slim: aprima automàticament executant l'aplicació i quedant-se només amb el que va tocar. Pot portar una imatge de 400 MB a 30 MB, i també pot trencar-la de manera silenciosa el dia que s'executi una ruta de codi que no es va provar durant l'anàlisi. Fes-lo servir amb una bateria de proves completa al darrere, i prefereix sempre arreglar el Dockerfile si hi tens accés.

  1. Seguretat

Eina Què analitza Moment Llicència
hadolint El Dockerfile, abans de construir Editor i CI GPL-3.0
Trivy Vulnerabilitats, secrets, IaC, SBOM CI i registre d'imatges Apache 2.0
Grype Vulnerabilitats (parella de Syft) CI, segona opinió Apache 2.0
Docker Scout Vulnerabilitats + recomanacions Escriptori i CI Propietària
Docker Bench Configuració de l'host i del daemon Auditoria periòdica Apache 2.0
Falco Comportament en temps d'execució Producció, continu Apache 2.0
Cosign Signatura i verificació d'imatges Publicació i admissió Apache 2.0

hadolint és el més barat d'adoptar i el que més problemes evita, perquè actua abans de construir res. Sobre una versió primerenca del Dockerfile de l'API:

docker run --rm -i hadolint/hadolint < Dockerfile
# Dockerfile:1 DL3006 warning: Always tag the version of an image explicitly
# Dockerfile:4 DL3009 info: Delete the apt-get lists after installing something
# Dockerfile:7 DL3016 warning: Pin versions in npm. npm install <package>@<version>
# Dockerfile:9 DL3020 error: Use COPY instead of ADD for files and folders
# Dockerfile:12 DL3002 warning: Last USER should not be root
# Dockerfile:14 SC2086 info: Double quote to prevent globbing and word splitting

Sis avisos que són exactament el temari dels mòduls 2 i 5: fixar la base, netejar memòries cau de paquets, fixar versions, COPY en lloc d'ADD, no acabar com a root i posar cometes a les variables dins de RUN. Sobre el Dockerfile actual d'aurora-api:2.0.0 no en surt cap, perquè la base està fixada per digest i l'USER final no és root. Integrar-lo costa quatre línies:

# .github/workflows/ci.yml (fragment)
- name: Lint del Dockerfile
  uses: hadolint/hadolint-action@v3
  with: { dockerfile: aurora-api/Dockerfile, failure-threshold: warning }

Falco és el que cobreix el buit que ningú més no cobreix: els altres analitzen artefactes aturats; Falco vigila syscalls en viu i alerta quan un contenidor fa alguna cosa que no hauria de fer —obrir una shell dins d'aurora-api, escriure a /etc, connectar-se a una IP desconeguda—. És l'última línia quan la vulnerabilitat no era a cap base de dades.

# Regla de Falco a mida per a Aurora Libros
- rule: Shell a aurora-api
  desc: L'API de producció no ha d'obrir mai una shell
  condition: spawned_process and container.image.repository contains "aurora-api"
             and proc.name in (sh, bash, ash)
  output: "Shell inesperada a aurora-api (usuari=%user.name cmd=%proc.cmdline)"
  priority: CRITICAL

Sobre les tres primeres de la taula: no cal triar-ne una de sola. Trivy al pipeline com a porta que fa fallar el build, Scout a l'escriptori per a la comprovació primerenca, i Grype com a segona opinió quan un resultat sorprèn. Cada escàner fa servir fonts diferents i no coincideixen sempre.

  1. Registres d'imatges propis

Opció Forta en Cost Quan
registry:2 Trivial d'aixecar, oficial Cap Laboratori, memòria cau local
Zot Només OCI, lleuger, signatura i cerca Baix Registre d'imatges propi modern
Harbor Usuaris, polítiques, escaneig, replicació, quotes Alt: és una plataforma Empresa amb governança
ghcr.io i similars Zero manteniment Subscripció El cas per defecte

Un ús que compensa gairebé sempre i que gairebé ningú no aplica: un mirall de Docker Hub a la xarxa local. Estalvia amplada de banda, esquiva els límits de descàrrega i manté el pipeline funcionant quan Hub té una mala tarda.

# compose.registre.yaml — mirall de només lectura de Docker Hub
services:
  mirall:
    image: registry:2
    ports: ["5000:5000"]
    environment:
      REGISTRY_PROXY_REMOTEURL: https://registry-1.docker.io
    volumes: ["registre-dades:/var/lib/registry"]
volumes: { registre-dades: }
// /etc/docker/daemon.json a cada host
{ "registry-mirrors": ["http://registre.intern:5000"] }

Harbor només es justifica quan hi ha diversos equips, polítiques de retenció, replicació entre regions i necessitat d'auditoria. És una plataforma amb base de dades, Redis i diversos components: algú l'ha de mantenir.

  1. Desenvolupament i proves

Eina Per a què Encaixa amb
Testcontainers Aixecar dependències reals des del test Qualsevol llenguatge; CI
Tilt Bucle intern amb Kubernetes: deses i veus el canvi Equips amb clúster
Skaffold Build+deploy continu cap a K8s Similar, més opinat
devcontainer Entorn de desenvolupament reproduïble a l'editor VS Code i compatibles
docker init Bastida inicial de Dockerfile i Compose Projectes nous

Testcontainers és la que més canvia la vida i la que menys es coneix. A 06-02 vas muntar serveis de PostgreSQL i Redis al workflow de CI; Testcontainers fa que el mateix test els aixequi, amb la qual cosa les proves s'executen igual al teu portàtil i al pipeline sense configuració duplicada:

// aurora-api/test/llibres.test.js — Node 22, node:test natiu
import { test, before, after } from 'node:test';
import assert from 'node:assert/strict';
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { GenericContainer, Wait } from 'testcontainers';
import { crearApp } from '../src/app.js';

let pg, redis, app;

before(async () => {
  pg = await new PostgreSqlContainer('postgres:16-alpine')
    .withDatabase('aurora_llibres').withUsername('aurora').withPassword('secret')
    .withCopyFilesToContainer([{ source: './db/init.sql',
                                 target: '/docker-entrypoint-initdb.d/init.sql' }])
    .start();

  redis = await new GenericContainer('redis:7-alpine')
    .withExposedPorts(6379)
    .withWaitStrategy(Wait.forLogMessage('Ready to accept connections'))
    .start();

  app = crearApp({
    dbUrl: pg.getConnectionUri(),
    redisUrl: `redis://${redis.getHost()}:${redis.getMappedPort(6379)}`
  });
});

after(async () => { await pg.stop(); await redis.stop(); });

test('GET /llibres retorna els nou títols del catàleg', async () => {
  const res = await app.inject({ method: 'GET', url: '/llibres' });
  assert.equal(res.statusCode, 200);
  const { llibres } = res.json();
  assert.equal(llibres.length, 9);
  assert.ok(llibres.some(l => l.titol === 'Rayuela'));
});

test('la segona lectura d\'un llibre ve de la memòria cau', async () => {
  await app.inject({ method: 'GET', url: '/llibres/3' });          // escalfa
  const res = await app.inject({ method: 'GET', url: '/llibres/3' });
  assert.equal(res.json().origen, 'cache');                        // cache-aside
});
node --test test/          # aixeca PostgreSQL i Redis, prova i els destrueix

El segon test és el que justifica l'eina: comprovar que el cache-aside retorna origen: cache exigeix un Redis de debò. Amb un doble de prova hauries validat el teu propi simulacre, no el comportament real. Testcontainers necessita un daemon accessible; a CI ja el tens, i funciona igual contra Podman amb el socket compatible (07-05).

Tilt i Skaffold resolen un altre problema: quan desenvolupes contra un clúster, el cicle build-push-deploy són minuts. Tots dos el redueixen a segons sincronitzant fitxers dins del Pod. Només compensen si el teu bucle intern és Kubernetes; si desenvolupes amb docker compose watch (04-07), no els necessites.

  1. Construcció sense Dockerfile

Eina Com construeix Forta en Límit
Buildpacks (pack) Detecta el llenguatge i aplica buildpacks Zero Dockerfile, pedaços de base automàtics Imatges més grans, menys control
Jib Plugin de Maven/Gradle, sense daemon Java: rapidíssim, capes òptimes Només JVM
ko Compila i empaqueta binaris Go Go: segons, imatge mínima Només Go
Nixpacks Dedueix l'entorn amb Nix Molt automàtic, fet servir per PaaS Menys conegut, reproduïble però opac
pack build aurora-api:pack --builder paketobuildpacks/builder-jammy-base
docker images aurora-api
# aurora-api  pack    412MB      ← davant dels 104 MB de la teva multietapa
# aurora-api  2.0.0   104MB

Aquí tens el compromís en una línia. Buildpacks t'estalvia escriure i mantenir el Dockerfile, i a canvi produeix una imatge quatre vegades més gran. Quan compensa?

Compensa no escriure Dockerfile Compensa escriure'l
Molts serveis petits i semblants Poques imatges, molt afinades
Ningú de l'equip no domina Docker Hi ha coneixement (tu ja el tens)
Es valora l'aplicació automàtica de pedaços a la base Es controla la base per digest
La mida i l'arrencada són indiferents La mida importa (edge, escalat)
Plataforma interna que estandarditza Requisits de seguretat específics

Per a Aurora Libros, amb una imatge ben optimitzada, multiarquitectura i signada, no compensa. Per a una plataforma interna amb quaranta microserveis, probablement sí.

  1. Neteja i manteniment

El disc s'omple sol. Automatitza-ho abans que et desperti una alerta:

# /etc/cron.weekly/docker-neteja — a cada host d'Aurora Libros
#!/bin/sh
docker image prune -a --filter "until=168h" -f     # imatges de més de 7 dies
docker builder prune --filter "until=168h" -f      # memòria cau de BuildKit
docker container prune --filter "until=24h" -f     # contenidors aturats
# MAI --volumes aquí: aurora-dades viu en un volum
docker system df >> /var/log/docker-neteja.log
Eina Què aporta Compte
docker system prune Natiu, suficient per a gairebé tot --volumes destrueix dades
docker builder prune --keep-storage Sostre fix a la memòria cau de BuildKit
docker-gc / docker-cleanup Polítiques més fines, contenidors Projectes amb manteniment desigual
Política de retenció del registre d'imatges Evita milers d'etiquetes velles Configura-la a ghcr.io o Harbor

El filtre until és la diferència entre una neteja segura i un pull complet l'endemà al matí. I la línia del comentari és la més important de l'script.

  1. Xarxa i diagnòstic

netshoot és una imatge amb totes les eines de xarxa que les teves imatges de producció, correctament, no porten: dig, curl, tcpdump, ss, iperf3, nmap.

# Depurar el DNS intern i la connectivitat d'Aurora Libros (05-01)
docker run --rm -it --network aurora-libros_posterior nicolaka/netshoot \
  sh -c 'dig +short aurora-db; nc -zv aurora-cache 6379'

# Ficar-se al namespace de xarxa del mateix contenidor de l'API
docker run --rm -it --network container:aurora-api nicolaka/netshoot \
  ss -tnp

La segona forma és la potent: --network container: comparteix el namespace de xarxa d'aurora-api (05-07), així que veus exactament les seves connexions i els seus ports sense instal·lar res a dins ni modificar la imatge. És el mateix que fa docker debug, amb una imatge pública i sense subscripció.

dockviz dibuixa l'arbre d'imatges i contenidors; útil per entendre un host heretat amb quaranta imatges d'origen desconegut.

  1. Criteris per adoptar una eina

Criteri Pregunta concreta Senyal d'alarma
Manteniment Hi ha commits i issues tancades els últims 6 mesos? Últim release fa dos anys
Llicència És compatible amb l'ús comercial que li donaràs? GPL en alguna cosa que redistribueixes; «gratis de moment»
Procedència Qui la publica? La imatge està signada? Imatge d'un usuari anònim de Hub
Criticitat Si desapareix demà, s'atura el desplegament? Un binari d'un sol autor a la ruta crítica
Comprensió Sap l'equip què fa per dins? «La vaig copiar d'un blog i funciona»
Sortida Quant costa treure-la? Formats propietaris, sense exportació
Superfície Necessita el socket de Docker o privilegis? Sí, i a més exposada a la xarxa
Solapament Fa alguna cosa que ja fas amb el que tens? Tres escàners que diuen el mateix

Dues regles d'or. Primera: com més a prop del pipeline, més exigent. Una TUI local que s'abandoni se substitueix en cinc minuts; un plugin que signa les teves imatges i deixa de rebre pedaços és un problema de seguretat i de desplegament alhora. Segona: valida amb el responsable de seguretat qualsevol eina que entri a la cadena de construcció o que necessiti el socket del daemon, i comprova'n la llicència amb qui correspongui abans d'integrar-la en un producte comercial. Afegir una dependència al pipeline és una decisió d'arquitectura, no una preferència personal.

  1. El kit mínim recomanat

Perfil Imprescindible Recomanable Prescindible
Aprenent lazydocker, dive hadolint Portainer, Tilt
Desenvolupador d'aplicació hadolint, dive, Testcontainers lazydocker, netshoot Buildpacks, Falco
DevOps / plataforma Trivy, Cosign, hadolint, netshoot Harbor o Zot, Falco, Portainer slim, Nixpacks
Operant en producció Trivy, Falco, Docker Bench, ctop Portainer, dockviz dive, docker init
Equip amb Kubernetes Trivy, Cosign, Tilt o Skaffold k9s, Harbor Dockge, lazydocker

Si només en poguessis adoptar tres per a la resta de la teva carrera: hadolint (evita errors abans de construir), Trivy (impedeix publicar alguna cosa vulnerable) i Testcontainers (fa que les teves proves signifiquin alguna cosa). Totes tres són de codi obert, estan mantingudes i no lliguen ningú.

Errors Habituals i Consells

  • Exposar Portainer o Dockge a Internet. Controlen el socket del daemon: qui hi entra és root a l'host. VPN o xarxa interna, sempre, i amb autenticació forta.
  • Instal·lar un plugin de logging sense provar la fallada de la destinació. Si la destinació no respon i el mode és bloquejant, els contenidors no arrenquen. Prova-ho amb Loki caigut a propòsit.
  • Confiar només en slim. Aprima observant una execució; el que no es va executar, desapareix. Sense una bateria de proves completa al darrere, és una bomba de rellotgeria.
  • Acumular tres escàners que diuen el mateix. Un com a porta del pipeline, un altre com a segona opinió puntual. Més només genera soroll que ningú no llegeix.
  • Afegir --volumes a la neteja programada. És la manera més ràpida de perdre aurora-dades un diumenge a la nit.
  • Adoptar una eina perquè va sortir en una conferència. Aplica-hi abans la taula de §12: manteniment, llicència, criticitat i cost de sortida.
  • Consell: posa hadolint al pipeline avui mateix. Costa quatre línies i evita mitja dotzena de males pràctiques per Dockerfile.
  • Consell: desa el plugin docker aurora al repositori. Les dreceres de l'equip deixen de viure a l'historial de bash de cadascú.
  • Consell: aprèn netshoot amb --network container:. Resol el 90 % de les depuracions de xarxa sense tocar la imatge.

Exercicis

Exercici 1 — Amplia docker aurora. Parteix del plugin de §2 i afegeix-hi tres subcomandes: escanejar, que executi Trivy sobre la imatge local de l'API i falli si hi ha vulnerabilitats crítiques; pesar, que mostri la mida de la imatge i executi dive --ci amb un llindar d'eficiència del 95 %; i xarxa, que llanci netshoot al namespace de xarxa d'aurora-api i comprovi que resol aurora-db i arriba a aurora-cache. El plugin ha de continuar funcionant sense instal·lar res més que Docker.

Exercici 2 — Lint i correcció d'un Dockerfile. Escriu a propòsit un Dockerfile dolent per a aurora-api (base sense etiqueta, apt-get sense netejar, ADD en lloc de COPY, npm install sense versió fixada, sense USER), passa-li hadolint i anota cada codi d'avís. Corregeix-los un a un fins que el lint quedi net, explicant en un comentari quin problema real evita cada correcció. Afegeix després la comprovació al pipeline amb llindar warning.

Exercici 3 — Avaluació d'adopció. Un company proposa afegir al pipeline una eina que optimitza automàticament les imatges abans de publicar-les. La publica un desenvolupador individual a Docker Hub, té 900 estrelles a GitHub, l'últim commit és de fa onze mesos i la imatge no està signada. Aplica la taula de criteris de §12 i escriu una resposta raonada: la teva recomanació, els tres riscos concrets que identifiques, i quines condicions s'haurien de complir perquè l'acceptessis.

Solucions

Solució 1.

# Afegir dins del case de ~/.docker/cli-plugins/docker-aurora
  escanejar)
    IMG="${2:-ghcr.io/auroralibros/aurora-api:2.0.0}"
    docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME/.cache/trivy:/root/.cache/trivy" \
      aquasec/trivy:latest image --severity CRITICAL,HIGH \
      --exit-code 1 --ignore-unfixed "$IMG"
    ;;
  pesar)
    IMG="${2:-ghcr.io/auroralibros/aurora-api:2.0.0}"
    docker image inspect "$IMG" --format 'Mida: {{.Size}} bytes ({{len .RootFS.Layers}} capes)'
    docker run --rm -e CI=true -v /var/run/docker.sock:/var/run/docker.sock \
      wagoodman/dive:latest --ci --lowestEfficiency 0.95 "$IMG"
    ;;
  xarxa)
    docker run --rm --network container:aurora-api nicolaka/netshoot sh -c '
      echo "DNS aurora-db -> $(dig +short aurora-db)"
      nc -zv aurora-cache 6379 && echo "cache accessible"
      ss -tnp | head -20'
    ;;
docker aurora escanejar && docker aurora pesar && docker aurora xarxa

Tres decisions importen més que la resta. El muntatge del socket és imprescindible perquè tant Trivy com dive inspeccionen imatges locals del daemon, no remotes; muntar ~/.cache/trivy evita descarregar la base de vulnerabilitats sencera a cada execució, que és el que fa que la primera vegada trigui un minut i les següents tres segons. L'--exit-code 1 converteix l'escaneig en una porta: sense ell, Trivy informa i retorna 0, i el pipeline passaria amb vulnerabilitats crítiques. I --ignore-unfixed evita el soroll de fallades que encara no tenen pedaç disponible, sobre les quals no pots actuar. A xarxa, --network container:aurora-api entra al namespace de xarxa del contenidor real (05-07), de manera que el que veus és la seva resolució DNS i les seves connexions, no les d'una xarxa qualsevol.

Solució 2. Dockerfile dolent i els codis que dispara:

FROM node                          # DL3006: sense etiqueta ni digest
RUN apt-get update && apt-get install -y curl   # DL3009/DL3015: sense netejar llistes
ADD . /app                         # DL3020: ADD per a fitxers locals
WORKDIR /app
RUN npm install                    # DL3016: sense versions fixades
CMD npm start                      # DL3025: CMD en forma shell
Codi Avís Problema real que evita
DL3006 Etiqueta la imatge base node és latest: el build no és reproduïble (05-04)
DL3009 Esborra les llistes d'apt ~40 MB d'escombraries permanents a la capa
DL3015 Fes servir --no-install-recommends Paquets que ningú no va demanar, més superfície d'atac
DL3020 COPY en lloc d'ADD ADD descomprimeix i descarrega URLs: comportament inesperat
DL3016 Fixa versions d'npm Un build avui i un altre demà instal·len coses diferents
DL3025 CMD en forma exec En forma shell, el procés no rep SIGTERM: adeu aturada ordenada (06-01)
DL3002 L'últim USER no ha de ser root Root al contenidor és root al kernel (05-03)

Versió corregida:

FROM node:22-alpine@sha256:1f8c...  AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev               # reproduïble des del lockfile

FROM node:22-alpine@sha256:1f8c...
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY --chown=node:node src ./src
USER node
CMD ["node", "src/index.js"]        # forma exec: PID 1 rep els senyals
docker run --rm -i hadolint/hadolint < Dockerfile   # sense sortida = net

L'avís que més se subestima és el DL3025: amb CMD npm start, PID 1 és un shell que no propaga SIGTERM, i tota l'aturada ordenada que vas muntar a 06-01 deixa de funcionar sense que cap test ho detecti. Es manifesta com a peticions tallades durant els desplegaments, i costa dies trobar-ho si no saps on mirar.

Solució 3. Recomanació: no adoptar-la al pipeline en el seu estat actual.

Criteri (§12) Avaluació
Manteniment Últim commit fa 11 mesos: si apareix una fallada, ningú no l'arregla
Procedència Autor individual, imatge sense signar a Hub: no pots verificar què executes
Criticitat Estaria a la ruta de publicació: si falla, no es desplega
Llicència Sense comprovar a l'enunciat; cal verificar-la abans de res
Comprensió «Optimitza automàticament» és una caixa negra sobre l'artefacte que va a producció

Els tres riscos concrets: (1) cadena de subministrament —una imatge sense signar d'un autor anònim, executant-se a CI amb accés a les teves imatges i probablement al socket, és exactament el vector que Cosign i les attestations de 06-02 van venir a tancar—; (2) trencament silenciós, perquè una optimització automàtica pot eliminar un fitxer que només es fa servir en una ruta poc freqüent, i ho descobriries en producció; (3) abandonament, ja que onze mesos sense commits en una eina que toca l'artefacte final significa que el dia que trenqui amb una versió nova de BuildKit, el desplegament s'atura i l'arreglada és teva.

Condicions per acceptar-la: que s'executi fora de la ruta crítica, com a informe comparatiu i no com a pas que modifica la imatge publicada; que la imatge estigui signada i fixada per digest; que existeixi una bateria de proves d'integració que validi la imatge optimitzada abans de publicar-la; i que el responsable de seguretat validi la llicència i la procedència. Contraproposta raonable: l'objectiu del company —imatges més petites— ja està cobert per la multietapa i dive --ci amb llindar, que són part del pipeline, no depenen de tercers i ja donen un 98 % d'eficiència sobre aurora-api:2.0.0. La conversa no és «no», és «aquest problema ja està resolt».

Conclusió

Ja tens l'equipament que envolta Docker i, més important, el criteri per triar-lo. Entens els tres nivells d'extensibilitat i la seva asimetria de risc: a la CLI experimenta lliurement, al daemon sigues conservador, perquè un plugin de logging bloquejat impedeix arrencar contenidors. I has construït el teu propi docker aurora amb quaranta línies de bash, descobrint que el mecanisme de docker compose i docker buildx és simplement un executable al PATH que respon a docker-cli-plugin-metadata.

Del recorregut per categories t'endús selecció, no catàleg: lazydocker i ctop per veure la flota sense teclejar, Portainer només quan hi ha diverses persones i diversos hosts, Dockge quan el que gestiones són piles de Compose; dive confirmant el 98 % d'eficiència que vas guanyar a 05-04 i servint de porta a CI amb --ci --lowestEfficiency, container-diff per auditar què va canviar entre versions i slim amb la seva advertència seriosa; hadolint assenyalant en sis avisos tot el temari dels mòduls 2 i 5 —inclòs el DL3025 que trenca l'aturada ordenada sense que cap test ho noti—, Trivy com a porta, Scout com a comprovació primerenca i Falco vigilant syscalls quan la vulnerabilitat no era a cap base de dades; el mirall de Docker Hub amb registry:2 que gairebé ningú no munta i gairebé sempre compensa; Testcontainers aixecant PostgreSQL i Redis des del mateix test per comprovar que el cache-aside retorna origen: cache de debò; Buildpacks amb el seu compromís mesurat —412 MB davant dels teus 104— i la taula de quan compensa no escriure un Dockerfile; la neteja programada amb until i sense --volumes; i netshoot amb --network container: entrant al namespace de xarxa d'aurora-api sense tocar la imatge.

I t'endús els criteris d'adopció, que valen més que qualsevol llista d'eines: manteniment actiu, llicència compatible, procedència verificable, criticitat al pipeline, comprensió real de l'equip, cost de sortida i superfície d'atac afegida. Amb les dues regles d'or: com més a prop del pipeline, més exigent, i valida amb el responsable de seguretat —i amb qui porti les llicències— qualsevol eina que entri a la cadena de construcció o demani el socket del daemon. Si t'haguessis de quedar amb tres per a la resta de la teva carrera: hadolint, Trivy i Testcontainers.

A la lliçó següent fem un pas enrere fonamental: Podman, containerd i l'estàndard OCI. Descobriràs per què les imatges que has anat construint tot el curs no són «de Docker», què normalitza exactament l'Open Container Initiative, i com ghcr.io/auroralibros/aurora-api:2.0.0 s'executa igual a Podman, a containerd o en un node de Kubernetes sense canviar ni un sol byte.

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