7.3 KiB
Docker explicado para usar ContainerFlow
Guía rápida: qué es Docker, conceptos clave, y qué hace cada acción de la app.
¿Qué es Docker?
Empaqueta tu app con todo lo que necesita (código, libs, configs) en una "caja" autocontenida que corre igual en cualquier máquina con Docker.
IMAGEN (plantilla) CONTAINERS (instancias)
┌──────────────┐ ┌──────────────┐
│ nginx:alpine │ ─────────► │ web-1 │
│ │ ─────────► │ web-2 │
│ │ ─────────► │ web-3 │
└──────────────┘ └──────────────┘
Una imagen es una plantilla congelada (receta + ingredientes). Un container es una instancia corriendo de esa imagen. Una imagen puede generar muchos containers.
Conceptos clave
| Concepto | Qué es | Ejemplo |
|---|---|---|
| Imagen | Plantilla inmutable con código + deps | nginx:alpine, postgres:15 |
| Container | Instancia corriendo de una imagen | fidelizacion-prod-auth-1 |
| Tag | Etiqueta legible de la imagen | :latest, :v1.2, :alpine |
| Image ID | Hash sha256 (identidad real de la imagen) | sha256:f4c41c... |
| Volumen | Persiste datos fuera del container | postgres-data, bind mounts |
| Red | Conecta containers entre sí | Containers en la misma red se ven por nombre |
| Compose | YAML que describe múltiples servicios | docker-compose.yml |
Acciones de ContainerFlow
Cada botón corresponde a un comando real de Docker. Lo que cambia es qué destruye y qué reusa:
Start: [exited] ─────► [running] (mismo container)
Stop: [running] ─────► [exited] (mismo container)
Restart: [running] ─────► STOP → START → [running] (mismo container)
Recreate: [running] ─────► REMOVE → CREATE → [running] (container NUEVO, misma imagen)
Rebuild: [running] ─────► BUILD IMAGE → REMOVE → CREATE → [running] (container NUEVO, imagen NUEVA)
Remove: [running] ─────► STOP → DELETE → ∅
Exec: [running] ─────► ejecuta comando dentro, container sigue igual
| Acción | Comando CLI | Cuándo lo usas |
|---|---|---|
| Start | docker start <c> |
Arrancar un container detenido |
| Stop | docker stop <c> |
Apagar limpio (SIGTERM, luego SIGKILL tras 10s) |
| Restart | docker restart <c> |
Reiniciar el proceso sin recrear nada (rápido) |
| Recreate | docker compose up -d --force-recreate <s> |
Aplicar cambios de compose (env, volumes, ports) sin rebuild |
| Rebuild | docker compose up -d --build <s> |
Aplicar cambios de código (reconstruye imagen) |
| Remove | docker compose rm -sf <s> |
Eliminar el container permanentemente (imagen queda) |
| Exec | docker exec <c> <cmd> |
Correr comando dentro (migrate, seed, redis-cli, etc.) |
Restart vs Recreate vs Rebuild
| Reinicia proceso | Recrea container | Reconstruye imagen | Aplica cambios compose | Aplica cambios código | |
|---|---|---|---|---|---|
| Restart | sí | no | no | no | no |
| Recreate | sí | sí | no | sí | no |
| Rebuild | sí | sí | sí | sí | sí |
Regla mental:
- Restart → algo cuelga, dale un reboot rápido
- Recreate → cambié compose (env var, volume), no toqué código
- Rebuild → cambié código, necesito la versión nueva
Identidad de un container
Hay dos cosas distintas y conviene no confundirlas:
Container Name: fidelizacion-prod-auth-1 ← legible, derivado de compose
ESTABLE entre recreates
Container ID: b0ab634b6eb2878677d85f8998ce1162... ← hash sha256
CAMBIA con cada recreate/rebuild
Lo mismo con imágenes:
Image Tag: fidelizacion-prod-auth:latest ← "apodo" legible
ESTABLE como puntero
Image ID: sha256:111aaa222bbb... ← hash de la imagen real
CAMBIA con cada rebuild
Cuando haces rebuild, el tag se "mueve" para apuntar al nuevo Image ID. La imagen vieja queda huérfana hasta que docker image prune la limpia.
Configuraciones comunes del compose
Restart policy
restart: unless-stopped
| Valor | Comportamiento |
|---|---|
no (default) |
Si muere, queda muerto |
always |
Lo reinicia siempre, incluso si tú lo detuviste |
on-failure |
Solo si murió con error (exit code != 0) |
unless-stopped |
Lo reinicia, excepto si lo detuviste manualmente (recomendado para prod) |
Resource limits
deploy:
resources:
limits:
cpus: "0.5" # máximo medio núcleo
memory: 256M # tope absoluto, el kernel lo mata si excede (OOM)
ContainerFlow muestra estos límites en el DetailPanel y los gráficos indican si te acercas al tope.
Volumes
volumes:
- postgres-data:/var/lib/postgresql/data # named volume (persiste)
- ./config.yml:/app/config.yml:ro # bind mount read-only
- Named volumes (
postgres-data) persisten entre recreate/rebuild — perfectos para DBs - Bind mounts conectan un directorio del host con el container
Healthcheck
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
retries: 3
Docker corre el test periódicamente. Si falla retries veces, marca el container como unhealthy. ContainerFlow muestra el estado en el nodo.
Estados de un container
| Estado | Significado |
|---|---|
running |
Corriendo normal |
exited |
Terminó (limpio o crash) |
paused |
Congelado con docker pause |
restarting |
En medio de reinicio (por restart policy) |
dead |
Falló mal, Docker no pudo limpiarlo |
crashed (label de ContainerFlow) |
Exit code != 0 |
ContainerFlow colorea los nodos: verde (healthy), rojo (exited/dead), amarillo (restarting/processing), naranja (unhealthy).
Preguntas frecuentes
¿Pierdo datos al hacer Rebuild? No si están en volumes (named volumes persisten siempre, bind mounts no se tocan). Sí si están solo en el filesystem del container — por eso las DBs siempre van en named volume.
¿Por qué Rebuild es lento?
Ejecuta docker build (descarga base, instala deps, compila). Recreate es segundos porque reusa la imagen existente.
¿Qué pasa si dos containers tienen el mismo nombre?
Docker rechaza. Por eso compose deriva nombres únicos: {project}-{service}-{replica}.
¿Qué es OOM Killed?
El container intentó usar más RAM que su memory limit y el kernel lo mató (out-of-memory). Visible en docker inspect.
¿Dónde viven físicamente los volúmenes?
- Named volumes:
/var/lib/docker/volumes/<nombre>/_data/ - Bind mounts: el directorio del host que pusiste en compose
¿Por qué algunos containers no tienen Rebuild en ContainerFlow?
Solo containers de compose. Los corridos con docker run directo no tienen compose file asociado.