Adopción de Docker en producción: lecciones de los primeros despliegues
Qué se hace mal cuando un equipo pasa de máquinas virtuales a contenedores: imágenes obesas, secretos en variables de entorno, falta de límites de recursos y dependencia del host.

La imagen no es un tar de tu home
Las primeras imágenes que un equipo construye suelen pesar 1-2 GB porque parten de ubuntu:latest, instalan build-essential y dejan dentro caches de apt, archivos de compilación y herramientas de desarrollo. Una imagen de producción debería ser multi-stage: una etapa para compilar, otra mínima (alpine o distroless) que sólo contenga el binario, sus librerías y los certificados.
FROM golang:1.19 AS build WORKDIR /src COPY . . RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app FROM gcr.io/distroless/static:nonroot COPY --from=build /out/app /app USER nonroot:nonroot ENTRYPOINT ["/app"]
Secretos, recursos y persistencia
Tres errores recurrentes: pasar contraseñas por ENV (quedan en el manifiesto, en docker inspect y en los logs del orquestador), no fijar memory/cpu limits (un contenedor mata al host en producción) y escribir datos en el filesystem del contenedor (se pierden en cada redeploy). Las soluciones son conocidas: secrets gestionados, requests/limits explícitos y volúmenes para todo dato persistente.
Observabilidad en un mundo efímero
Un contenedor reiniciado pierde sus logs locales. Stdout/stderr a un colector central (Fluentd, Loki, journald-remote), métricas expuestas en /metrics y trazas con un identificador de correlación que sobreviva al ciclo de vida del contenedor. Sin esto, debugar un incidente en producción se convierte en arqueología.
