docker run y configuración de runtime | Nicolás Garzón
una instancia concreta
Texto
Copiar image inmutable
+ command y environment
+ usuario y privilegios
+ network y puertos
+ mounts
+ límites de recursos
+ políticas de lifecycle
→ containerDos contenedores creados desde el mismo digest pueden comportarse distinto si reciben variables, mounts, redes, comandos o recursos diferentes. Por eso la identidad del artefacto no basta para reproducir una ejecución: también debes versionar o documentar su configuración.
Bash
Copiar docker run -d \
--name api \
--env-file .env.production \
--network backend \
-p 127.0 .0.1:3000:3000 \
--mount type = volume,src= api-data,dst= /app/data \
--memory 512m \
--cpus 1 \
--pids-limit 200 \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size= 64m \
--restart unless-stopped \
registry.example.com/api@sha256:.. .
dónde se ejecuta la imagen;
cómo se identifica la instancia;
qué configuración recibe;
cómo se comunica;
qué datos persisten;
cuánto puede consumir;
qué puede modificar;
cómo se recupera de un crash.
Cuando la configuración crece, muévela a Compose o infraestructura como código. Un docker run enorme es difícil de revisar, repetir y auditar.
Texto
Copiar resolver image
→ pull si hace falta
→ create container
→ aplicar configuración
→ start process
→ attach o detachPuedes separar las operaciones:
Bash
Copiar docker create --name api my-api:1.0
docker inspect api
docker start apiEsto ayuda a distinguir un fallo de creación de un fallo del proceso al arrancar.
Bash
Copiar docker run --name api my-api:1.0El nombre facilita referencias humanas:
Bash
Copiar docker logs api
docker inspect api
docker stop apiSin --name, Docker genera uno. Los nombres deben ser únicos dentro del Engine.
No confundas nombre con identidad durable. Al recrear, puedes reutilizar api, pero el nuevo contenedor tiene otro ID, otra writable layer y posiblemente otra IP.
Bash
Copiar docker run --rm alpine echo holaLa terminal recibe stdout/stderr. La finalización del proceso devuelve control y exit code.
Bash
Copiar docker run -d --name api my-apiLa CLI devuelve el ID y el proceso sigue. Revisa después:
Bash
Copiar docker logs -f api
docker inspect api --format '{{json .State}}' -d no convierte el proceso en un daemon interno. PID 1 continúa controlando el lifecycle.
Bash
Copiar docker run -it --rm alpine sh En CI evita -t salvo necesidad: puede alterar buffering, caracteres y detección de terminal.
Bash
Copiar docker run --rm my-tool generateElimina el contenedor cuando termina. Es apropiado para:
CLIs;
jobs efímeros;
conversiones;
pruebas;
tareas cuyo resultado sale por stdout o mount.
Durante diagnóstico puede ser inconveniente porque desaparecen inspect, exit metadata y writable layer. Conserva telemetría externa o ejecuta temporalmente sin --rm.
docker
Copiar ENTRYPOINT ["node"]
CMD ["server.js"]Bash
Copiar docker run my-api
Bash
Copiar docker run my-api worker.js
Bash
Copiar docker run --rm --entrypoint node my-api --version Usa overrides para tareas relacionadas y diagnóstico, no para ocultar un diseño defectuoso donde producción siempre necesita sustituir la intención de la imagen.
Bash
Copiar docker run \
--env NODE_ENV = production \
--env PORT = 3000 \
my-apiBash
Copiar docker run --env-file .env.production my-apiLas variables son visibles para el proceso y pueden aparecer en docker inspect. No son un secret manager ideal.
validar variables al iniciar;
distinguir obligatorias y opcionales;
no usar defaults inseguros;
fallar rápido con mensajes sin secretos;
documentar formato y unidades.
Bash
Copiar docker run --user 10001 :10001 my-apiSobrescribe el usuario predeterminado. Puede reducir privilegios, pero también provocar fallos de permisos si la imagen esperaba escribir como root.
Bash
Copiar docker run --rm my-api id
docker inspect my-api --format '{{.Config.User}}' No uses --user root como solución permanente a ownership incorrecto. Corrige Dockerfile y mounts.
Bash
Copiar docker run --workdir /app my-api node script.jsSobrescribe WORKDIR. El path debe existir o ser utilizable según el runtime. Un working directory distinto puede cambiar resolución de archivos y configuración.
Bash
Copiar docker run --hostname api-01 my-apiEl hostname interno no reemplaza service discovery. En networks definidas por usuario, usa nombres y aliases de red. No dependas de una IP efímera.
Bash
Copiar docker network create backend
docker run -d --network backend --name db postgres:17
docker run -d --network backend --name api my-apiLa API puede conectar a db:5432.
Conectar a varias networks:
Bash
Copiar docker network connect observability apiCada conexión amplía los destinos alcanzables. Diseña conectividad mínima.
Bash
Copiar docker run -p 127.0 .0.1:8080:3000 my-apiTexto
Copiar host 127.0.0.1:8080
→ container port 3000Bash
Copiar docker run -p 8080 :3000 my-apipuede enlazar en todas las interfaces, según plataforma y configuración. Esto puede exponer el servicio a la red.
EXPOSE 3000 no publica nada. La aplicación además debe escuchar en 0.0.0.0, no solo 127.0.0.1 dentro del container.
Prefiere --mount por claridad:
Bash
Copiar docker run \
--mount type = volume,src= db-data,dst= /var/lib/postgresql/data \
postgres:17Bash
Copiar docker run \
--mount type = bind,src= "$PWD " ,dst= /app,readonly \
my-toolBash
Copiar docker run --tmpfs /tmp:rw,noexec,nosuid,size= 64m my-api
lifecycle;
ownership;
read-only o writable;
capacidad;
backup;
portabilidad entre hosts;
comportamiento si el path falta.
Un mount cubre el contenido de la imagen en la ruta destino.
Bash
Copiar docker run --memory 512m my-apiLa aplicación puede ser terminada por OOM si excede el límite. Ajusta heap, buffers y concurrencia.
Bash
Copiar docker run --cpus 1.5 my-apiLimita tiempo de CPU; no garantiza rendimiento reservado.
Bash
Copiar docker run --pids-limit 200 my-apiReduce impacto de fork bombs o creación descontrolada de procesos.
Ciertos workloads, como browsers o bases, usan /dev/shm. Ajusta solo con evidencia:
Bash
Copiar docker run --shm-size 256m my-browser-testBash
Copiar docker run --read-only my-apiDescubre escrituras ocultas y reduce persistencia del atacante.
Añade únicamente paths necesarios:
Bash
Copiar docker run \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size= 64m \
--mount type = volume,src= uploads,dst= /app/uploads \
my-apiBash
Copiar docker run --privileged my-api--privileged amplía acceso a devices y capacidades y desactiva varias fronteras.
Bash
Copiar docker run \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges \
my-apiAñade solo lo justificado. Muchos servicios en puertos altos no necesitan capabilities adicionales.
Bash
Copiar docker run --device /dev/video0 my-camera-appExponer devices concede acceso específico al hardware y requiere modelo de amenaza. No uses privileged para evitar entender el device requerido.
Bash
Copiar docker run --restart unless-stopped my-apiAyuda a recuperar crashes locales, pero no proporciona:
HA;
failover de host;
rollback;
dependencia saludable;
escalado.
Un error determinista puede convertirse en crash loop.
Puede sobrescribirse o deshabilitarse según opciones y versión. Un healthcheck debe verificar una condición significativa, con timeout y sin efectos secundarios.
El estado healthy no garantiza disponibilidad futura. La aplicación debe tolerar pérdida de dependencias.
Bash
Copiar docker run -d \
--label com.nicoo.project = wiki \
--label com.nicoo.environment = production \
my-apiSirven para ownership, filtros, automatización y limpieza segura.
Bash
Copiar docker ps --filter label = com.nicoo.project= wikiNo son una prueba de confianza: cualquier actor con permisos de creación puede escribirlas.
El logging driver y sus opciones afectan retención y disco.
Bash
Copiar docker run \
--log-opt max-size= 10m \
--log-opt max-file= 3 \
my-apiLas opciones exactas dependen del driver. Sin rotación, un servicio activo puede llenar el host.
Bash
Copiar docker run --pull = always registry.example.com/api:stableFuerza resolver el tag, pero sigue siendo mutable. Para reproducibilidad:
Bash
Copiar docker run registry.example.com/api@sha256:.. .Registra digest y configuración. Un host nuevo debe poder obtener el artefacto.
Bash
Copiar docker run --stop-timeout 30 my-apiAlinea el timeout con el graceful shutdown real. Un valor largo no corrige una aplicación que ignora SIGTERM.
Bash
Copiar docker run -d \
--name api \
--network backend \
--env-file /etc/my-api/runtime.env \
--mount type = volume,src= api-uploads,dst= /app/uploads \
-p 127.0 .0.1:3000:3000 \
--user 10001 :10001 \
--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 \
--label com.nicoo.service = api \
registry.example.com/api@sha256:.. .
El digest fija el artefacto.
Environment vive fuera de la image.
El puerto solo está disponible localmente para un reverse proxy.
Uploads persisten en volume.
Root filesystem es read-only.
No existen capabilities adicionales.
Recursos están limitados.
La configuración todavía debe versionarse en un sistema más declarativo.
Bash
Copiar docker ps -a --filter name = '^/api$'
docker inspect api --format '{{json .State}}'
docker logs api
proceso running;
app escucha en 0.0.0.0;
puerto interno correcto;
publicación correcta;
interfaz del host;
firewall;
proxy.
Bash
Copiar docker inspect api --format '{{json .Mounts}}'
docker exec api id Si no hay shell, inspecciona desde host o debug image. Evita cambiar a root sin entender ownership.
Bash
Copiar docker inspect api --format '{{.State.OOMKilled}}'
docker stats --no-stream apiBash
Copiar docker inspect api --format '{{.RestartCount}}'
docker events --since 10m --filter container = apiLos bind mounts usan paths del host remoto, no de la máquina con la CLI.
La metadata desaparece. Usa logging externo o conserva la instancia durante investigación.
Un nuevo api no es la misma instancia. Verifica ID, image digest y timestamps.
--env NAME puede tomar el valor del shell o producir comportamiento distinto según invocación. Prefiere valores y validación explícitos.
Un servicio pensado solo para reverse proxy puede quedar expuesto públicamente.
Identifica paths legítimos y monta únicamente esos; no retires toda la protección.
Consecuencia: drift y recuperación difícil.
Corrección: Compose, systemd unit generada o infraestructura como código.
Consecuencia: un container puede degradar todo el host.
Corrección: medir y definir límites con alertas.
Consecuencia: rompe gran parte del aislamiento.
Corrección: identificar capability o device exacto.
Consecuencia: exposición innecesaria.
Corrección: network interna y acceso mediante servicios autorizados.
Consecuencia: pérdida al recrear.
Corrección: volume o servicio externo.
Consecuencia: hosts ejecutan artefactos distintos.
Corrección: registrar y desplegar digest.
docker run materializa image + configuración + estado.
El mismo digest puede producir instancias diferentes.
Puertos, mounts, usuarios y privilegios son decisiones de seguridad.
Límites protegen el host, pero deben medirse.
La configuración importante debe ser declarativa y versionable.
Reinicio local no equivale a alta disponibilidad.
Comprueba lo aprendido
Explica qué partes de un contenedor provienen de la image y cuáles del runtime.
Diseña un docker run para una API detrás de un reverse proxy con root filesystem read-only.
¿Por qué el mismo tag puede producir resultados diferentes entre hosts?
¿Qué investigarías ante permission denied en un volume?
¿Cuándo debes abandonar un comando manual y usar Compose?
Variables de entorno y configuración , donde se diseña la separación entre artefacto, defaults, configuración por ambiente y secretos.