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
- Els tres nivells d'extensibilitat
- Construeix el teu propi
docker aurora - Plugins del daemon i extensions de l'escriptori
- Interfícies de gestió
- Inspecció i optimització d'imatges
- Seguretat
- Registres d'imatges propis
- Desenvolupament i proves
- Construcció sense Dockerfile
- Neteja i manteniment
- Xarxa i diagnòstic
- Criteris per adoptar una eina
- El kit mínim recomanat
- 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.
- Construeix el teu propi
docker aurora
docker auroraEl 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}" ;;
esacchmod +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.
- 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).
- 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/lazydockerAmb 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.
- 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:
# 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.0Sobre 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.
- 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 splittingSis 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: CRITICALSobre 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.
- 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: }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.
- 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
});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.
- 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 104MBAquí 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í.
- 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.
- 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 -tnpLa 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.
- 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.
- 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
--volumesa la neteja programada. És la manera més ràpida de perdreaurora-dadesun 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
hadolintal pipeline avui mateix. Costa quatre línies i evita mitja dotzena de males pràctiques per Dockerfile. - Consell: desa el plugin
docker auroraal repositori. Les dreceres de l'equip deixen de viure a l'historial de bash de cadascú. - Consell: aprèn
netshootamb--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'
;;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 senyalsL'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
- 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
