Reducir el tamaño de una imagen de Docker puede significar ahorro en costos de nube, despliegues más rápidos y un sistema más eficiente. Aquí verás cómo pasar de una imagen de 1.19 GB a 126 MB en Docker para .NET usando Alpine, y qué reglas prácticas seguir al elegir tu imagen base sin comprometer rendimiento ni seguridad.
¿Por qué el tamaño de la imagen Docker importa para producción?
Optimizar el tamaño no es un capricho: en sistemas distribuidos y despliegues frecuentes, mover muchas imágenes pesadas consume ancho de banda, tiempo y dinero. Subir cientos de imágenes de alrededor de un gigabyte a la nube puede volverse muy costoso. En cambio, una imagen ligera acelera pull/push, reduce almacenamiento y simplifica la operación.
¿Qué datos clave demuestran la diferencia?
Imagen base estándar de .NET alrededor de 1.19 GB.
Imagen optimizada con Alpine de 126 MB.
Reducción cercana a 10x en el ejemplo mostrado.
En escenarios con muchas imágenes, el impacto económico y operativo se multiplica.
¿Qué habilidades y conceptos se aplican aquí?
Optimización de imágenes Docker: enfoque en reducir tamaño sin perder funcionalidad.
Elección de imagen base: comparar .NET 8.0 vs .NET 8.0-alpine y su efecto.
Flujo de construcción: usar docker build con tag (-t) para versionar y auditar.
Verificación en Docker Desktop: confirmar el tamaño final de la imagen.
¿Cómo optimizar una imagen .NET con Alpine paso a paso?
La clave está en cambiar las bases a versiones alpine tanto en la etapa de compilación como en la de ejecución. Además, conviene ordenar el Dockerfile: definir un directorio de trabajo, copiar archivos correctamente y publicar con dotnet publish.
# Antes: base estándar (más pesada)
FROM ...:8.0
...
FROM ...:8.0
...
# Después: base ligera Alpine
FROM ...:8.0-alpine
WORKDIR /app
COPY . .
RUN dotnet publish
FROM ...:8.0-alpine
...
Crea el proyecto y agrega un Dockerfile en la raíz.
Consejo útil: el nombre del archivo Dockerfile puede ir en mayúsculas o minúsculas, es equivalente.
Asegura que el nombre del proyecto (.csproj) y la DLL coincidan en el Dockerfile.
Construye con: docker build -t dependencias ..
Revisa el tamaño en Docker Desktop y compara.
¿Qué ajustes del Dockerfile marcan la diferencia?
Cambiar de SDK 8.0 a SDK 8.0-alpine.
Cambiar de runtime 8.0 a runtime 8.0-alpine.
Usar un directorio de trabajo consistente (por ejemplo, app).
Copiar los archivos necesarios al directorio de trabajo y ejecutar dotnet publish.
¿Qué herramientas apoyan el flujo de trabajo?
Visual Studio Code y su control de versiones ayudan a ubicar rápido cambios.
Docker Desktop para inspeccionar imágenes y validar tamaños.
¿Qué reglas seguir para elegir la imagen base adecuada?
La elección de imagen base define tamaño, rendimiento y seguridad. No existe una única respuesta: depende del contexto del proyecto.
Regla 1: entre más pequeña sea la imagen, mejor. Acelera despliegues y reduce costos.
Regla 2: no sacrifiques rendimiento. La aplicación debe funcionar con la calidad esperada.
Regla 3: no sacrifiques seguridad. Prioriza imágenes y configuraciones seguras.
En algunos escenarios, una imagen grande es necesaria por requisitos específicos. En otros, Alpine funciona de maravilla porque la aplicación es pequeña. Cada caso es distinto; aprende a evaluar tu contexto con estas reglas.
¿Tú qué estrategia usas para reducir imágenes en .NET con Docker? Comparte tu experiencia y dudas en los comentarios.
Me atrevería a decir que esta clase es una continuación de "multi-stage"
En el minuto 1:25 el profe utilizo el comando dotnet new webapi -n Dependecies para crear un nuevo proyecto, asumo que el comendo dotnet es una especie de framework que ayuda a crear una estructura de proyecto según el lenguaje a usar.
Dónde puedo ubicar mas informacion sobre como utilizar el framework para otros lenguajes o arquitecturas?
Con algo de busque logre identificar que se trata de un template de .Net en Linux para crear proyectos con este lenguaje por lo que pensaria que podrian existir framework o project templates para otros.
Es como hacer un proyecto con python con los diferentes frameworks como fastapi u otros basados en MVC
Probé compilando un proyecto de Rust, el cual es un lenguaje compilado que no tiene runtime. Hice pruebas para un proyecto llamado broot (https://github.com/Canop/broot), y definí dos Dockerfile para probar la diferencia entre imágenes Debian e imágenes Alpine.
Dockerfile de la imagen Debian:
FROM rust:1.92-trixie as builderWORKDIR /appRUN apt updateRUN apt install build-essential libxcb1-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev -yCOPY . .RUN cargo build --releaseFROM debian:trixie-slim as runnerWORKDIR /appCOPY--from=builder /app/target/release/broot .CMD \["./broot"]
Dockerfile de la imagen Alpine:
FROM rust:1.92-alpine AS builderWORKDIR /appRUN apk updateRUN apk add build-base libxcb-devCOPY . .RUN cargo build --releaseFROM alpine:latest as runnerWORKDIR /appCOPY--from=builder /app/target/release/broot .CMD \["./broot"]
En lo personal pasar de version 8 a 8-alpine me rebajo 120mb, muy buenos jeje
Por eso justo menciono el maestro que hizo el ejemplo con aplicaciones .NET, ya que la version base es bastante pesada en comparación con su version reducida
que grande es la diferencia de tamaño de imagen! excelente optimización!
para los compañeros que descargaron el proyecto de github, deben verificar de que le faltan líneas al dockerfile de Dependencies.
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build-env
WORKDIR /App
COPY Dependencies.csproj .
RUN dotnet restore
COPY . .
RUN dotnet build "Dependencies.csproj" -c Release -o /App/build
RUN dotnet publish "Dependencies.csproj" -c Release -o /App/out
FROM mcr.microsoft.com/dotnet/runtime:8.0-alpine
WORKDIR /App
COPY --from=build-env /App/out .
EXPOSE 5000
ENTRYPOINT ["dotnet", "Dependencies.dll"]
Concuerdo en que esta clase pudo ser una extensión del MultiStage y haber modificado ese Dockerfile, para ver cómo se optimiza el espacio. Es bueno uno ir practicando y viendo las diferencias, para así memorizar mejor.
si, y falto mas en esa otra clase, pero bueno.
**Cuando desplegamos muchas imágenes a un sistema distribuido, debemos considerar el peso de esas imágenes, incluso si cada una pesa 1 GB. Si necesitamos subir 150 imágenes de 1 GB, el costo de almacenamiento y transferencia puede ser considerablemente alto.**Entonces, ¿cómo podemos reducir este tamaño?
La solución más eficiente es utilizar una imagen base más pequeña. Alpine Linux es una distribución minimalista, diseñada específicamente para ser liviana, lo que permite reducir significativamente el tamaño de las imágenes Docker.
Por ejemplo, en lugar de usar una imagen pesada como node:16, podemos optar por node:16-alpine:
FROM node:16-alpine
Esto puede reducir el tamaño de la imagen hasta 10 veces. Cuando comparamos las imágenes construidas en Docker Desktop, observamos que la versión con Alpine es mucho más ligera en comparación con una imagen base más grande.
En mi caso la imagen 9.0-alpine pesa 990MB y la 9.0 1.2GB. Una diferencia pequeña :/
solo cambió la distro :v
Utilice esta imagen para procesos de desarrollo (desarrollo, construcción y prueba de aplicaciones).
mcr.microsoft.com/dotnet/sdk Esta imagen contiene el SDK de .NET, que consta de tres partes:
CLI de .NET
Entorno de ejecución de .NET
ASP.NET Core
Es la razón del tamaño de las imágenes
Esta imagen mcr.microsoft.com/dotnet/runtime contiene los entornos de ejecución y las bibliotecas de .NET y está optimizada para ejecutar aplicaciones .NET en producción.
o Esta imagen mcr.microsoft.com/dotnet/aspnet contiene los entornos de ejecución y las bibliotecas de ASP.NET Core y .NET, y está optimizada para ejecutar aplicaciones ASP.NET Core en producción.
Bello no?
Optimizar el tamaño de las imágenes Docker es clave para reducir costos y mejorar la eficiencia, especialmente en proyectos distribuidos con .NET. Se pueden lograr ahorros significativos reduciendo el tamaño de las imágenes.
Estrategias:
Imágenes base ligeras: Usar versiones alpine (ej. mcr.microsoft.com/dotnet/aspnet:8.0-alpine) reduce drásticamente el tamaño.
Consolidar pasos: Minimizar las capas en el Dockerfile.
Eliminar dependencias innecesarias: Incluir solo lo esencial.
Esto se verifica construyendo y comparando el tamaño con docker build y docker images. Es importante recordar que una imagen pequeña reduce costos de almacenamiento y acelera los despliegues.
Siempre prioriza:
Tamaño reducido.
Rendimiento.
Seguridad.
Al final el tamaño si importa xd, hay que tener en cuenta que cuanto no se tienen recursos ilimitados debemos ser muy creativos en como optimizar recursos y poder aprovechar mejor los recursos
Yo tengo una duda, he estado practicando con varias imágenes, ahora solo tengo una de 1.6 GB pero en mi almacenamiento se ha consumido demasiado espacio, no sé si es algo de mi configuración que tenga que limitar o si cada build o versión se almacena también
No entiendo cual es la optimizacion que tu le haces. Simplemente cambiar la imagen?
Porque no comenzar de la buena de una vez.
Supongo que lo hace para mostrar que es importante revisar bien a la hora de escoger una imagen base. SI vemos el docker registry hay cientos y miles de imagenes, que podríamos utilizar cualquiera. Si mejor buscamos con la intención de elegir la mas liviana o la que mejor se adapte a nuestro proyecto, esto nos ayudará a optmizar recursos y precios
Interesante, no hizo nada, solo cambio la imagen y redujo su tamaño para una version mini... entiendo que esto te quita un monton de cosas que luego si quieres agregarlas volvera a crecer ok