Modelo mental completo de Docker | Nicolás Garzón
Dockerfile
Texto
Copiar source + lockfiles
→ build context
→ Dockerfile + BuildKit
→ layers + config + manifest
→ image identificada por digest
→ registry
→ configuración de runtime
→ container process
→ namespaces + cgroups + mounts + networks
→ health + logs + métricas + traces
→ rollout + rollback + backup + recoveryCada flecha representa una frontera donde pueden introducirse diferencias, vulnerabilidades, pérdida de datos o fallos de operación. La meta no es únicamente “hacer que la aplicación corra”, sino producir un artefacto trazable, ejecutar un proceso reemplazable y operar el sistema sin depender de cambios manuales.
Texto
Copiar Docker empaqueta un filesystem y una configuración de proceso en una image inmutable,
y crea containers que ejecutan esa image con aislamiento y configuración de runtime sobre un host compartido.El aislamiento proviene principalmente del kernel: namespaces separan vistas del sistema y cgroups controlan recursos. La image define defaults; el runtime decide cómo se ejecuta una instancia concreta.
El proceso empieza antes del Dockerfile.
Texto
Copiar repository
├── source
├── package manifests
├── lockfiles
├── Dockerfile
├── configuración de build
└── archivos que no deberían enviarseel punto final representa el build context . El builder solo puede acceder a archivos presentes en ese contexto, excepto recursos entregados mediante mecanismos explícitos como secret mounts, SSH mounts o fuentes remotas soportadas.
source necesario;
lockfiles;
archivos de configuración de compilación;
assets requeridos;
Dockerfile o rutas relacionadas.
.git cuando no sea necesario;
node_modules del host;
.env reales;
credenciales;
logs;
outputs antiguos;
caches;
archivos personales;
artefactos grandes no utilizados.
.dockerignore es una frontera de seguridad y rendimiento:
Texto
Copiar menos archivos enviados
→ menor riesgo de filtración
→ cache más estable
→ builds más rápidosUn secreto excluido del COPY pero incluido en el context sigue habiendo sido enviado al builder. Por eso debes controlar el context completo.
El Dockerfile describe cómo producir una image. No es un script de provisionamiento de servidor tradicional.
docker
Copiar # syntax=docker/dockerfile:1
FROM node:22-bookworm-slim AS dependencies
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci
FROM dependencies AS build
COPY . .
RUN npm test && npm run build
FROM node:22-bookworm-slim AS production-dependencies
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
npm ci --omit=dev
FROM node:22-bookworm-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY --from=production-dependencies --chown=node:node /app/node_modules ./node_modules
COPY --from=build --chown=node:node /app/dist ./dist
COPY --chown=node:node package.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]Este ejemplo expresa varias decisiones:
instalación reproducible mediante lockfile;
cache separada del resultado;
tests y compilación en etapas de build;
runtime sin dependencias de desarrollo;
usuario no root;
command en exec form;
artefactos copiados explícitamente.
BuildKit interpreta el Dockerfile como un grafo de operaciones y puede ejecutar etapas independientes en paralelo, reutilizar cache y montar recursos temporales.
Texto
Copiar COPY manifests
→ install dependencies
→ copy source
→ test/build
→ assemble runtimeLa cache funciona correctamente cuando cada operación declara todos sus inputs. Si un paso usa un archivo que no fue copiado antes o depende de estado externo invisible, el resultado puede quedar desactualizado.
docker
Copiar COPY package.json package-lock.json ./
RUN npm ci
COPY src ./srcCambiar src no invalida la instalación de dependencias.
docker
Copiar COPY . .
RUN npm ciCualquier cambio invalida todo y el context puede incluir ruido.
docker
Copiar RUN --mount=type=cache,target=/root/.npm npm ciEl cache acelera descargas, pero no forma parte automáticamente de la layer resultante. Debe tratarse como optimización, no como fuente de verdad.
Credenciales necesarias durante la construcción no deben enviarse con ARG, ENV o COPY.
docker
Copiar RUN --mount=type=secret,id=npmrc,target=/root/.npmrc,required=true \
npm ciBash
Copiar docker build \
--secret id = npmrc,src= "$HOME /.npmrc" \
. El secret existe temporalmente durante esa instrucción. Sin embargo, el proceso todavía puede copiarlo, imprimirlo o incorporarlo a un artefacto. El mount reduce exposición; no elimina la responsabilidad del comando consumidor.
Build secrets y runtime secrets son distintos:
Texto
Copiar build secret → producir la image
runtime secret → ejecutar la aplicaciónEl password de producción de la database no debe existir durante build.
Cada instrucción que modifica el filesystem produce un resultado cacheable y normalmente contribuye a una layer.
Texto
Copiar base layer
+ paquetes
+ dependencias
+ artefactos
→ filesystem de la imageLas layers son inmutables. Borrar un archivo en una instrucción posterior no lo elimina del blob anterior.
docker
Copiar COPY secret.txt /secret.txt
RUN use-secret
RUN rm /secret.txtEl archivo puede seguir recuperable desde layers históricas.
Consecuencia: evita introducir el secreto, no intentes borrarlo después.
layers de filesystem;
configuración como Env, User, WorkingDir, Entrypoint y Cmd;
metadata;
manifest;
referencias a blobs;
identidad por digest.
Texto
Copiar image
├── manifest
├── config object
└── layersLa image no es un proceso en ejecución. Es un artefacto inmutable que puede crear muchas instancias.
Un tag es una referencia mutable:
Texto
Copiar api:1.8.2
api:stable
api:latestUn digest identifica contenido:
Texto
Copiar api@sha256:abc...Texto
Copiar CI construye digest A
→ tests aprueban A
→ staging ejecuta A
→ producción ejecuta ASi producción reconstruye desde el mismo commit, puede obtener digest B debido a cambios en bases, dependencias o tooling. Por eso se promueve el mismo digest, no el mismo source.
El registry almacena manifests, blobs, tags y, según soporte, attestations como SBOM y provenance.
Texto
Copiar push
→ registry almacena blobs y manifests
→ tag apunta al digest
pull
→ cliente resuelve referencia
→ descarga blobs faltantes
→ verifica contenido por digestLa autenticación del registry debe usar permisos mínimos. Un token de push no debe estar disponible en una pull request no confiable.
La retención del registry debe conservar:
release actual;
releases de rollback;
attestations;
artefactos necesarios para incident response.
docker run combina varias operaciones:
Texto
Copiar resolve/pull image
→ create container
→ aplicar configuración
→ start process
→ attach o detachBash
Copiar docker run -d \
--name api \
--network backend \
--env-file /etc/api/runtime.env \
-p 127.0 .0.1:3000:3000 \
--mount type = volume,src= uploads,dst= /app/uploads \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size= 64m \
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 512m \
--cpus 1 \
--pids-limit 200 \
--restart unless-stopped \
registry.example.com/api@sha256:.. .La image es la misma; estas opciones crean una instancia específica.
Texto
Copiar Docker CLI
→ Docker daemon
→ container runtime management
→ OCI runtime
→ proceso aislado por el kernelEl daemon administra images, containers, networks y volumes del host. Componentes como containerd y el runtime OCI participan en el lifecycle de ejecución.
El detalle de implementación puede evolucionar, pero el modelo estable es:
Texto
Copiar cliente solicita intención
→ daemon prepara recursos
→ runtime crea namespaces/cgroups/mounts
→ kernel ejecuta el procesoQuien controla el daemon normalmente tiene capacidad administrativa sobre el host. El socket de Docker no es un archivo ordinario.
El lifecycle del container depende del proceso principal.
Texto
Copiar PID 1 termina
→ container terminadocker
Copiar CMD ["node", "dist/server.js"]Evita una shell innecesaria:
docker
Copiar CMD node dist/server.jsLa aplicación debe manejar SIGTERM:
Texto
Copiar SIGTERM
→ dejar de aceptar tráfico
→ drenar requests/jobs
→ cerrar pools
→ salir antes del timeoutSi ignora la señal, Docker termina usando SIGKILL tras el periodo de gracia. SIGKILL no permite cleanup.
--init puede ayudar a reenviar señales y recolectar procesos hijos, pero no sustituye graceful shutdown de la aplicación.
Los namespaces separan vistas del sistema.
El container ve su propio árbol de procesos.
Tiene interfaces, rutas, DNS y puertos propios.
Ve un filesystem y mounts específicos.
Aísla hostname y domain name.
Separa ciertos mecanismos de comunicación entre procesos.
Puede mapear identidades internas a IDs no privilegiados del host.
El aislamiento no significa kernel separado. Todos los containers Linux del mismo host comparten el kernel.
Los cgroups contabilizan y limitan recursos:
Texto
Copiar processes del container
→ cgroup
→ memory / CPU / PIDs / I/OBash
Copiar --memory 512m
--cpus 1.5
--pids-limit 200 Un límite no garantiza rendimiento. Puede producir:
OOM;
CPU throttling;
incapacidad de crear threads;
latencia de I/O.
Dimensiona con carga real y observa p95/p99, RSS, heap, queue depth y event loop lag.
Son controles diferentes.
Texto
Copiar USER non-root
→ proceso no usa UID 0 dentro del container
user namespace
→ UID interno se mapea a ID no privilegiado del host
rootless mode
→ daemon y containers se ejecutan sin root real del host
secretos entregados a la app;
una network demasiado amplia;
un Docker socket montado;
vulnerabilidades de negocio;
consumo de recursos sin límites.
Linux divide privilegios de root en capabilities.
Bash
Copiar docker run \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
imageUna API que escucha en 3000 probablemente no necesita capabilities adicionales.
Seccomp limita syscalls. AppArmor y SELinux pueden restringir acceso a paths y recursos. No desactives controles globalmente para resolver un permission denied; identifica la capa exacta.
--privileged amplía drásticamente el acceso y debe evitarse salvo workload especializado y aislado.
Al crear un container, Docker añade una writable layer sobre las layers inmutables.
Texto
Copiar image layers read-only
+ container writable layer
→ filesystem combinadoCambios en writable layer desaparecen al eliminar el container.
database;
uploads durables;
logs históricos;
configuración manual;
secrets persistentes.
Bash
Copiar --read-only
--tmpfs /tmp:size= 64m
--mount type = volume,src= uploads,dst= /app/uploadsCada path escribible debe tener un propósito explícito.
Storage administrado por Docker o un driver.
Texto
Copiar container eliminado
→ named volume permaneceNo implica backup ni supervivencia a pérdida del host.
Conecta un path real del host.
Texto
Copiar host /srv/config.yaml
↔ container /app/config.yamlReduce portabilidad y puede exponer/modificar el host.
Storage temporal en memoria.
Texto
Copiar container se recrea
→ contenido desapareceÚtil para /tmp, sockets y datos temporales. Debe limitarse para evitar presión de memoria.
¿debe sobrevivir al proceso?
¿debe sobrevivir al container?
¿debe sobrevivir al host?
¿debe replicarse entre zonas?
¿cómo se respalda?
¿cómo se restaura?
¿qué RPO/RTO exige?
Un volume resuelve principalmente el segundo punto. Backups externos, replicación o servicios administrados resuelven otros niveles.
Cada container tiene su propio namespace de red.
Texto
Copiar localhost dentro de api
→ api mismaNo significa database ni host.
En una user-defined bridge:
Docker DNS resuelve el service/container name. No uses IPs internas fijas.
Pertenece al proceso dentro del container.
Documenta intención; no publica.
Bash
Copiar -p 127.0 .0.1:8080:3000Crea una ruta desde host 127.0.0.1:8080 hacia container 3000.
Entre containers de la misma network no necesitas publicar el puerto.
Texto
Copiar internet
→ proxy
→ API
→ database
worker
→ queue
→ databaseYAML
Copiar services :
proxy :
networks : [ edge, backend]
api :
networks : [ backend, data]
worker :
networks : [ queue, data]
db :
networks : [ data]
redis :
networks : [ queue]
networks :
edge :
backend :
internal : true
data :
internal : true
queue :
internal : true Network isolation reduce reachability, pero no reemplaza autenticación, TLS ni roles mínimos.
La misma image debe funcionar en desarrollo, staging y producción.
Texto
Copiar image digest A + config development
image digest A + config production
environment para configuración simple no sensible;
archivos montados para estructura;
secret files/manager para credenciales;
servicios dinámicos para flags/config avanzada.
Todas las variables llegan como strings. Valida tipos, unidades, valores obligatorios y defaults.
No imprimas process.env completo.
Un secret montado como archivo reduce exposición en metadata comparado con environment, pero la aplicación todavía puede leerlo y filtrarlo.
scope por service;
permisos mínimos;
rotación;
revocación;
expiración;
auditoría;
comportamiento durante reload/recreate.
La app no debe recibir credenciales más poderosas que las operaciones que realiza.
Texto
Copiar running ≠ healthy ≠ ready
running: PID 1 existe;
healthy: el check ha pasado;
ready: puede recibir tráfico útil.
Un healthcheck debe ser barato, determinista y sin efectos secundarios.
depends_on puede coordinar arranque, pero no protege contra la caída posterior de una dependencia.
La aplicación debe implementar:
timeouts;
retries con backoff y jitter;
reconexión;
límites de concurrencia;
circuit breaking cuando aplique;
degradación controlada.
Responden qué ocurrió. Escribe stdout/stderr en formato estructurado.
Muestran tendencias y saturación.
Relacionan operaciones entre servicios.
Muestran lifecycle del Engine: create, die, OOM, health, network y volume.
service;
environment;
version;
digest;
commit;
request ID;
trace ID;
host/node.
Configura rotación local y centralización. Un container activo puede llenar el disco con logs.
Compose convierte configuración de runtime en un modelo declarativo.
Texto
Copiar compose.yaml
→ services
→ networks
→ volumes
→ containers del proyectoUn service es una identidad lógica; un container es una instancia.
Bash
Copiar docker compose config
docker compose up -d
docker compose ps --all
docker compose logs -f
docker compose run --rm api npm run migrate
docker compose downrestart no aplica una nueva image/configuración. up puede recrear.
down -v elimina volumes del proyecto y es destructivo.
El project name participa en los nombres reales; cambiarlo puede crear otro conjunto de resources.
Compose no es un control plane multi-host.
No aporta automáticamente:
scheduling entre nodos;
rescheduling por pérdida de host;
rollout distribuido avanzado;
autoscaling completo;
desired state de cluster;
HA de datos.
Puede ser suficiente para desarrollo, CI y producción single-host con riesgo aceptado y recovery probado.
Un orquestador mantiene estado deseado:
Texto
Copiar desired replicas: 3
actual replicas: 2
→ crea reemplazoAporta scheduling, service discovery multi-host, rollout y políticas. Pero no resuelve mágicamente:
datos locales;
migrations incompatibles;
bugs deterministas;
falta de capacidad;
database topology.
Adopta la plataforma mínima que satisfaga SLO, RTO y escala de forma sostenible.
La confianza empieza antes del runtime.
Texto
Copiar source protegido
→ builder autorizado
→ dependencies fijadas
→ image por digest
→ SBOM + provenance + scan + firma
→ policy verificationBusca vulnerabilidades conocidas.
Describe cómo y desde qué source se construyó.
Vincula una identidad con un digest.
Ninguno demuestra seguridad total. Se complementan.
Texto
Copiar checkout exacto
→ lint/test
→ build target test
→ build runtime
→ smoke test image final
→ SBOM/provenance/scan
→ push digest
→ firma
→ staging
→ verificación
→ promoción del mismo digest
→ producciónNo reconstruyas por ambiente.
digest anterior disponible;
configuración compatible;
schema compatible;
procedimiento probado;
criterios claros.
Volver la image no deshace una migration destructiva.
Un tag multi-platform apunta a un índice:
Texto
Copiar api:1.8.2
├── linux/amd64 manifest
└── linux/arm64 manifest
base compatible;
dependencias nativas correctas;
tests;
scan;
SBOM;
verificación de arranque.
Emulación facilita builds pero no sustituye totalmente hardware real.
escuchar en 0.0.0.0;
validar environment al iniciar;
usar lockfile y npm ci;
ejecutar Node directamente como proceso principal;
manejar SIGTERM;
cerrar HTTP server, workers y pools;
escribir stdout/stderr;
no guardar estado durable local;
respetar memory limit y backpressure;
exponer health/readiness.
Docker no corrige un event loop bloqueado, un memory leak o un shutdown mal implementado.
Containerizar PostgreSQL o MongoDB estandariza el proceso, no vuelve reemplazables los datos.
volume/ruta correcta;
roles y secrets mínimos;
health y métricas del motor;
migrations coordinadas;
backups consistentes;
restore probado;
upgrade soportado;
capacity de I/O y disco;
réplica/failover cuando el SLO lo exige.
Un restart policy no es alta disponibilidad.
Producción exige operar el sistema completo:
hosts parcheados;
daemon/socket restringidos;
digests aprobados;
TLS y proxy;
firewall;
runtime endurecido;
limits;
state externalizado;
observabilidad;
backups;
rollout/rollback;
alertas y runbooks;
disaster recovery.
Un single host puede ser válido cuando el downtime es aceptable y existe un RTO realista. Debes reconocer que es un punto único de fallo.
Cuando algo falla, sigue este orden:
Texto
Copiar 1. context/cliente
2. daemon/host
3. image/registry
4. create config
5. process/PID 1
6. filesystem/mounts
7. DNS/network/ports
8. resources/cgroups
9. aplicación/dependenciasBash
Copiar docker context show
docker info
docker ps -a
docker inspect container
docker logs --timestamps container
docker events --since 30m
docker stats --no-stream
docker network inspect network
docker system df -v
docker compose configInterpreta el tipo de error:
DNS failure: nombre/network;
connection refused: ruta llegó, no listener;
timeout: ruta, firewall o proceso bloqueado;
TLS error: transporte funciona, confianza falla;
HTTP 500: red funciona, aplicación falla;
exit 137: SIGKILL posible, no prueba OOM sin evidencia;
permission denied: puede ser UID/GID, read-only, SELinux, seccomp o capability.
No reinicies antes de preservar evidencia salvo que necesites mitigar impacto inmediato.
Docker consume disco mediante:
images/layers;
build cache;
stopped containers;
writable layers;
logs;
volumes;
data de Desktop/registry.
Bash
Copiar df -h
df -i
docker system df -v
docker ps -a --size
docker buildx du Limpia por categoría y política. Un volume no conectado puede contener la última copia de datos.
Bash
Copiar docker system prune -a --volumes Un sistema Docker saludable conserva estas reglas:
No se edita después de construir. Los cambios producen un nuevo digest.
Eliminarlo y recrearlo no debe perder datos de negocio ni configuración irreemplazable.
Volumes, databases y object storage se administran fuera de la writable layer.
La misma image se usa en distintos ambientes.
Tags ayudan a humanos; digests prueban contenido.
Usuario, capabilities, mounts, networks y credentials son solo los necesarios.
Signals, retries, health, logging y backpressure no se resuelven solo con flags de Docker.
Backup, restore, rollback y lost-host recovery deben ejecutarse antes de necesitarlos.
Texto
Copiar 1. desarrollador cambia source y lockfile
2. CI revisa y ejecuta tests
3. BuildKit recibe context controlado
4. secrets temporales autorizan dependencias privadas
5. multi-stage produce runtime mínimo
6. scanner revisa resultado
7. SBOM/provenance se asocian al digest
8. registry almacena image y attestations
9. staging despliega ese digest
10. smoke/integration tests verifican runtime
11. producción promueve el mismo digest
12. nueva instancia alcanza readiness
13. tráfico cambia gradualmente
14. versión anterior drena y termina por SIGTERM
15. métricas y logs confirman SLO
16. digest anterior permanece disponible para rollbackEn cada paso existe evidencia auditable.
YAML
Copiar services :
proxy :
image : caddy: 2
ports :
- "80:80"
- "443:443"
networks : [ edge, backend]
volumes :
- proxy- data: /data
api :
image : registry.example.com/api@sha256: API_DIGEST
user : "1000:1000"
read_only : true
cap_drop : [ ALL]
security_opt :
- no- new- privileges: true
environment :
NODE_ENV : production
PORT : "3000"
DATABASE_HOST : db
DATABASE_PASSWORD_FILE : /run/secrets/db_password
secrets : [ db_password]
tmpfs :
- /tmp: size=64m, noexec, nosuid
networks : [ backend, data]
mem_limit : 512m
cpus : 1.0
pids_limit : 200
stop_grace_period : 30s
healthcheck :
test : [ "CMD" , "node" , "healthcheck.js" ]
interval : 10s
timeout : 3s
retries : 5
start_period : 20s
worker :
image : registry.example.com/api@sha256: API_DIGEST
command : [ "node" , "dist/worker.js" ]
user : "1000:1000"
read_only : true
cap_drop : [ ALL]
security_opt :
- no- new- privileges: true
environment :
DATABASE_HOST : db
DATABASE_PASSWORD_FILE : /run/secrets/db_password
secrets : [ db_password]
networks : [ queue, data]
db :
image : postgres: 17
environment :
POSTGRES_USER : app
POSTGRES_DB : app
POSTGRES_PASSWORD_FILE : /run/secrets/db_password
secrets : [ db_password]
volumes :
- db- data: /var/lib/postgresql/data
networks : [ data]
healthcheck :
test : [ "CMD-SHELL" , "pg_isready -U app -d app" ]
interval : 5s
timeout : 3s
retries : 10
redis :
image : redis: 8
networks : [ queue]
volumes :
proxy-data :
db-data :
networks :
edge :
backend :
internal : true
data :
internal : true
queue :
internal : true
secrets :
db_password :
file : /run/secure- material/db- passwordEste modelo todavía necesita fuera del archivo:
backup y restore de PostgreSQL;
rotación del secret;
logs y métricas centralizados;
TLS/config del proxy;
registry y CI/CD;
host patching;
deployment y rollback;
recovery ante pérdida del host.
Compose describe el runtime, no toda la operación.
¿Qué digest exacto se ejecuta?
¿La base está mantenida?
¿Las dependencias son reproducibles?
¿Existe SBOM y provenance?
¿Hay secretos en layers o metadata?
¿Quién es PID 1?
¿Maneja SIGTERM?
¿Qué usuario ejecuta?
¿Qué capabilities conserva?
¿Qué paths necesita escribir?
¿La misma image funciona en todos los ambientes?
¿Qué valores son secretos?
¿Cómo se validan?
¿Cómo se rotan?
¿Qué se pierde al eliminar el container?
¿Qué se pierde al perder el host?
¿Existe backup externo?
¿El restore está probado?
¿Cómo se actualiza el formato?
¿Qué services pueden comunicarse?
¿Qué puertos están publicados y en qué interfaz?
¿Existe TLS y autenticación?
¿Cómo se resuelve DNS/reconexión?
¿Cuánta memory/CPU/PIDs consume normalmente?
¿Qué ocurre al alcanzar límites?
¿Existe backpressure?
¿Hay capacidad para rollout y recovery?
¿Qué logs, métricas y traces existen?
¿Cómo se identifica el deployment?
¿Cómo se hace rollback?
¿Qué ocurre si falla el host o registry?
¿Qué runbooks existen?
puedes recrear containers sin miedo;
puedes demostrar qué digest está desplegado;
no necesitas entrar a editar producción;
un secret puede rotarse mediante procedimiento;
los datos tienen backup y restore probado;
los puertos internos no se publican por comodidad;
la aplicación termina limpiamente;
un OOM, fallo DNS o disk full puede diagnosticarse por evidencia;
el deployment tiene criterios de éxito y rollback;
el host puede reconstruirse desde configuración e inventario;
el equipo conoce qué riesgos acepta deliberadamente.
“no borres ese container porque tiene cambios”;
“no sabemos qué tag está corriendo”;
“los datos deben estar en algún volume”;
“solo funciona con privileged”;
“reinícialo hasta que funcione”;
“producción se construye directamente en el servidor”;
“el backup nunca se ha restaurado”;
“todos los servicios usan la misma network”;
“no hay límites porque Docker ya aísla”;
“Compose nos da alta disponibilidad”.
Cada frase indica una frontera no diseñada.
Construye una API con PostgreSQL y worker y demuestra:
Dockerfile multi-stage con test target.
npm ci y lockfile.
Build secret para registry privado simulado.
Runtime no root y read-only.
SIGTERM y graceful shutdown.
Health/readiness.
Compose con networks separadas.
Database en named volume.
Secret montado como archivo.
Limits de memory, CPU y PIDs.
Logs JSON con request/trace ID.
Backup y restore en volume nuevo.
Build amd64/arm64.
SBOM, scan y digest.
Despliegue del mismo digest en dos ambientes.
Simulación de pérdida de container sin pérdida de datos.
Simulación de OOM, DNS roto y disk pressure.
Rollback al digest anterior.
El proyecto está completo cuando puedes explicar cada decisión, no solo cuando devuelve HTTP 200.
Docker transforma source en un artefacto y ese artefacto en un proceso aislado.
La image es inmutable; el container es una instancia reemplazable.
Namespaces aíslan vistas; cgroups controlan recursos; el kernel sigue compartido.
Volumes conservan estado fuera del container, pero no sustituyen backup ni HA.
DNS interno y networks conectan services; port publishing cruza hacia el host.
Configuración y secretos pertenecen al runtime, no a las layers.
La aplicación debe manejar señales, health, retries, logs y backpressure.
Compose modela una aplicación single-host; un orquestador administra estado deseado multi-host.
CI/CD construye una vez y promueve por digest.
Seguridad, observabilidad, recuperación y capacidad forman parte de Docker en producción.
El mejor diseño no es el que usa más funciones, sino el que hace explícitos artefacto, privilegios, estado, fallos y recuperación.
Comprueba lo aprendido
Explica el recorrido completo desde un commit hasta un proceso en producción.
Diferencia image, container, writable layer, volume y registry.
Diseña el aislamiento de proxy, API, worker, Redis y PostgreSQL.
Describe cómo responderías a un secret encontrado en una layer publicada.
Explica por qué un container non-root con Docker socket sigue siendo peligroso.
Diseña un rollout y rollback compatibles con migrations.
Diagnostica un container running que no responde desde el host.
Define qué cambia al pasar de Compose a un orquestador.
Diseña backup y restore para una database containerizada.
Enumera la evidencia necesaria para demostrar qué artefacto se desplegó.