Aprende Docker → Lección 10
La última lección es la que da sentido a las nueve anteriores. Todo lo visto —imágenes inmutables, configuración fuera, etiquetas trazables— existe para que esto sea posible: validar algo en QA y publicar exactamente eso en producción, con la certeza de que no cambió por el camino.
La regla: construir una vez, promover siempre
El flujo correcto tiene cuatro pasos y solo uno de ellos construye:
# 1. La integración continua construye UNA vez, al fusionar docker build -t registro.ejemplo.com/mi-app:$COMMIT . docker push registro.ejemplo.com/mi-app:$COMMIT # 2. QA descarga esa imagen y la arranca con su configuración docker pull registro.ejemplo.com/mi-app:$COMMIT docker run -d --env-file qa.env registro.ejemplo.com/mi-app:$COMMIT # 3. Se valida en QA # 4. Producción arranca LA MISMA, con otra configuración docker run -d --env-file produccion.env registro.ejemplo.com/mi-app:$COMMIT
Entre el paso 2 y el 4 no hay ningún build. Eso es lo esencial. Si en el paso 4 se reconstruyera, entre una construcción y otra podrían cambiar una dependencia transitiva, una versión de la imagen base o un parche de seguridad del sistema, y lo que se publica dejaría de ser lo validado.
mi-app:2bbc62e pasaría a apuntar a otra cosa. El digest no, porque es la huella del contenido. En entornos donde esto importe, el despliegue debería fijar mi-app@sha256:af364ec0... en vez de la etiqueta.Que el contenedor sepa decir si está sano
Un contenedor «arrancado» no es un contenedor que funcione: el proceso puede estar vivo y la aplicación no responder. HEALTHCHECK resuelve esa diferencia:
HEALTHCHECK --interval=5s --timeout=3s --retries=3 \ CMD curl -fsS http://localhost/salud || exit 1
El estado aparece en la propia lista de contenedores:
docker ps, recién arrancadoUp 1 second (health: starting)
docker ps, unos segundos despuésUp 9 seconds (healthy)
docker inspect --format '{{.State.Health.Status}}' mi-contenedorhealthy
Eso es lo que permite un despliegue sin corte: se levanta el contenedor nuevo, se espera a que diga healthy, y solo entonces se le manda tráfico y se retira el viejo. Sin comprobación de salud, el único criterio es «el proceso arrancó», que no significa gran cosa.
Revertir, que es la parte que se olvida
Si las imágenes están etiquetadas por commit, volver atrás es arrancar la anterior:
docker run -d --env-file produccion.env registro.ejemplo.com/mi-app:e97a329
No hay que reconstruir, ni revertir el repositorio, ni esperar a la integración continua. La imagen anterior sigue en el registro intacta. Esta es la razón práctica más fuerte para no desplegar por latest: con etiquetas móviles la versión anterior deja de ser localizable justo cuando más falta hace.
Una lista para el despliegue
| Comprobación | Por qué |
|---|---|
| La imagen se construyó una sola vez | Es lo que garantiza que QA y producción son lo mismo |
| La etiqueta identifica el commit | Trazabilidad y reversión |
| La configuración viene de fuera | Si no, harían falta dos imágenes |
Hay HEALTHCHECK |
Para saber cuándo está listo de verdad |
| El proceso corre sin privilegios | USER en el Dockerfile; root por defecto es un riesgo |
| Hay límites de memoria y CPU | --memory, --cpus: que un contenedor no tumbe la máquina |
| La política de reinicio está puesta | --restart unless-stopped |
| Los registros van a la salida estándar | Para que los recoja la plataforma, no un archivo dentro |
| Sabes cómo revertir | Y lo has probado alguna vez |
Y aquí se cierra el curso
La idea que resume las diez lecciones es que Docker no es sobre todo una herramienta de empaquetado, sino una forma de eliminar la incertidumbre del despliegue. La imagen inmutable, la configuración fuera y la etiqueta trazable sirven todas al mismo fin: que la pregunta «¿qué hay exactamente en producción?» tenga una respuesta exacta, y que volver atrás sea una orden y no una noche en vela.