Optimización Avanzada en Docker

1

La importancia de Aprender Docker

2

Desbloqueando el Poder de Docker

3

Construcción de Imágenes Multi-stage

4

Escaneo de imágenes en Docker

5

Optimización de Imágenes de docker con Distroless

6

Compilación Multiplataforma

7

Gestión de Caché y Eficiencia en Builds

8

Reducción de Dependencias y Minimización de Tamaño

9

Optimización de Build Context y Reducción de Transferencias

10

Explorando Docker Hub

Buenas Prácticas en Docker

11

Uso Eficiente de Capas en Imágenes Docker

12

Uso de .dockerignore para Optimización

13

Eliminación de Archivos Temporales y Residuos en Docker

14

Agrega usuarios a tu imagen de docker

15

Mejores Prácticas para Construcción de Imágenes

Instalación y Configuración en Entornos Multiplataforma

16

Despliegue de Docker en Azure y Entornos Locales

17

Publicar tu imagen a Container Apps de Azure

Redes Avanzadas y Balanceo de Carga

18

Modelos de Red en Docker

19

Exposición y Publicación de Puertos en Docker

20

Balanceo de Carga con Docker

Automatización de CI/CD

21

Ejecución de Scripts Multi-line en Docker

22

Automatización de CI/CD con Docker

23

Estrategias Avanzadas de CI/CD en Docker

24

Publicando mi imagen de docker a la nube con CI/CD

Orquestación

25

Retomando Docker Compose

26

Secciones en un archivo Docker Compose

27

Agregando volúmenes con Docker Compose

28

Secuencia de apagado

29

Introducción a Docker Swarm

30

Replicación de Stacks con Docker Compose

31

De Docker a la nube

32

Orquestadores de contenedores

33

Costos de Docker

Develop

34

Introducción a los devcontainers

You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
1 Hrs
56 Min
33 Seg

Construcción de Imágenes Multi-stage

3/34
Resources

How to create efficient Docker images?

Creating efficient Docker images is essential for any developer or technology professional looking to optimize their applications and working environments. Here's how you can start creating images that are not only functional, but also lightweight and easy to maintain.

When starting to create images with Docker, the main goal is to keep the Dockerfile as simple as possible. This reduces the chances of errors and makes it easier to manage and update images.

What is a Dockerfile and how is it structured?

A Dockerfile is a text file that contains all the instructions needed to create a Docker image. For example, for a Python back-end application, the basics would be:

FROM python:3.8WORKDIR /appCOPY . /appRUN pip install -r requirements.txtCMD ["python", "app.py"]

This simple example installs the requirements and copies the files needed to run the application. However, for more complex projects, this simple structure can quickly grow in size.

What are multi-stage builds?

In larger projects, using Docker with multi-stage builds can be critical. Why? Because it allows you to build smaller, optimized images by selecting only the necessary components.

Let's look at an example with ASP.NET, where Visual Studio creates a multi-stage Dockerfile. An example of a multi-stage Dockerfile could be:

# Stage 1 - Build the applicationFROM mcr.microsoft.com/dotnet/sdk:5.0 AS buildWORKDIR /srcCOPY ["MyApp.csproj", "./"]RUN dotnet restore "MyApp.csproj"COPY . .RUN dotnet build "MyApp.csproj" -c Release -o /app/build
 # Stage 2 - Publish the applicationFROM build AS publishRUN dotnet publish "MyApp.csproj" -c Release -o /app/publish
 # Stage 3 - Build the runtime imageFROM mcr.microsoft.com/dotnet/aspnet:5.0WORKDIR /appCOPY --from=publish /app/publish .ENTRYPOINT ["dotnet", "MyApp.dll"]

How do multiple stages reduce the size of the image?

By using multiple stages, we ensure that only the necessary files are included at the end of the process. Dependencies and development files that are not necessary for the deployment of the application are removed.

First the application is compiled, only the assemblies are published and then copied to the final container. This means that the final container size is considerably smaller, which is more efficient for deploying and scaling applications in production.

Why is it important to optimize the use of Docker?

Implementing these practices allows you to not only reduce the size of images and optimize their use, but also helps improve development time. Upgrades become a simple process, and containerized infrastructure offers greater flexibility and control, which is essential in microservices and devops environments.

By following these practical tips, you can ensure that your projects are agile, efficient and prepared for any technical challenges that come your way - go ahead and continue to explore and optimize the use of Docker in your future developments!

Contributions 8

Questions 0

Sort by:

Want to see more contributions, questions and answers from the community?

Aquí mi resumen de la clase. **Imágenes muti-stage**: Técnica para la construcción de imágenes optimizadas y eficientes. Es util cuando tenemos herramientas pesadas que no son necesarias en la imagen final que se ejecutará en producción. **Beneficios** * Reducción del tamaño de la imagen final: Solo incluye extrictamente lo necesario. * Eficiencia en el proceso de construcción: Reutiliza etapas previas de compilación y reduce redundancias.
Encontré un dockerfile que usa **multi-stage con python** 🐍: ```python # Primera imagen para compilar FROM python:3.8.4-slim-buster as compile-image # Se define una variable opcional RUN python3 -m venv /opt/venv # Se sobreescribe la variable path para que tenga prioridad los comandos del ambiente ENV PATH="/opt/venv/bin:$PATH" # Se copia unicamente el archivo de dependencias COPY requirements.txt /requirements.txt # Se instalan las dependencias. RUN pip install -r requirements.txt # Listo, inicia el segundo contenedor FROM python:3.8.4-alpine3.12 AS build-image # Se copia la carpeta venv que contiene todas las dependencias en el segundo contenedor COPY --from=compile-image /opt/venv /opt/venv # Se copia la aplicación COPY . usr/src/app # Se establece por defecto el directorio WORKDIR /usr/src/app # Se agrega el directorio a las variables de ambiente. ENV PATH="/opt/venv/bin:$PATH" # Arranca la aplicación ENTRYPOINT python3 main.py `````` aquí te cuento algunas cosas que me sorprendieron:   **1 etapa o primer contendor**   \- En esta etapa solo compila la imágen de python: instala dependencias y demás: El docker quedará sucio y pesado. \- `FROM python:3.8.4-slim-buster as compile-image` la versión slim-buster te da la imagen que compila con C. Por lo que es adecuada para correr numpy, keras y todo lo relacionado con machine learning.   \- la línea `RUN python3 -m venv /opt/venv` asigna una carpeta para el entorno virtual.   \- la línea `ENV PATH="/opt/venv/bin:$PATH"` asigna el entorno virtual a las variables de entorno de linux 🤯  (así todo corre en el entorno virtual y no en el sistema operativo del docker)   \- las dependencias se instalarán en el entorno virtual: `RUN pip install -r requirements.txt` **2 etapa o segundo contendor** \- La primera etapa deja el docker lleno de caché y basura que solo hace el docker más pesado. Por lo que en esta segunda etapa, se crea un nuevo docker que sí va a ser usado.   \- `FROM python:3.8.4-alpine3.12 AS build-image` descarga la imágen de python que funciona con alpine. *¡Alpine es la distro de linux más liviana que existe! 🪶*   \- la línea `COPY --from=compile-image /opt/venv /opt/venv` copia las dependencias del contenedor sucio y las pega en el directorio opt/venv (ya sabes el entorno virtual) \- aquí **SÍ** copias el proyecto de tu vsc local `COPY . usr/src/app`, en un contenedor limpio. Para que todo dev siempre sepa dónde buscar el proyecto, déjalo en usr/src/app. <u>Así millones de devs te lo agradecerán</u> \- Creas el Workdir, nuevamente asignas el path para que todas las dependencias se instalen allí y ENTRYPOINT arranca el archivo que necesites. Espero te haya servido ~ @camilocsoto
Un archivo Dockerfile es un script de texto que contiene una serie de instrucciones para automatizar la creación de una imagen de Docker. Estas instrucciones definen cómo se debe configurar el entorno, qué aplicaciones se deben instalar y cómo se deben ejecutar. Las líneas en un Dockerfile pueden incluir comandos como `FROM` para especificar la imagen base, `RUN` para ejecutar comandos en la construcción de la imagen, y `COPY` para añadir archivos desde el sistema local al contenedor. Utilizar Dockerfiles permite crear imágenes optimizadas y reproducibles, facilitando el despliegue de aplicaciones en contenedores.
Con esta clase pasé de tener una imagen en 800 MB a menos de 200 M, increible!
No sé si alguien más llegó a esta conclusión y no estoy seguro si el profe lo explica. Pero quiero decir que la construcción multi-stage resulta muy útil cuando trabajamos con un **lenguaje compilado**. Pero si el **lenguaje es interpretado** me temo que no hay mucho que hacer mas que tratar de utilizar las versiones alpine de dichos lenguajes, porque a la final necesitan de todas esas dependencias para funcionar. Puede rascarse un poco pero no es tan significativo como en el primer caso.
Por si alguien se encuentra desarrollando un proyecto con Anaconda3, se pueden construir contenedores a partir de estas imágenes: `FROM continuumio/miniconda3` `FROM condaforge/miniforge3` Además les dejo este link en el que me encontré un ejemplo de construcción de imágenes multi-stage usando Anaconda3 [*<u>https://github.com/pabpereza/dockerfile-best-practices/blob/main/python/miniconda/Dockerfile</u>*](https://github.com/pabpereza/dockerfile-best-practices/blob/main/python/miniconda/Dockerfile)
Chicos, por si alguien se perdio... En este dockerfile hacemos varios pasos digamoslo asi, para generar contenedores que para nosotros es 1 solo. Primera fase que el le dice "build" miren el as build. Le decimos WORKDIR es como el cd de la consola de docker. Luego agarramos el .csproj, que es como el package.json de js con las dependencias de ese proyecto de net. Y lo copiamos a dentro de la carpeta de docker . en este caso /src. Luego hacemos un dotnet restore, que es un comando de .net para que se instalen las dependencias, luego hacemos el copy de siempre, osea todo el proyecto de nosotros local, hacia el docker. Luego, corremos 2 comandos con RUN, donent build blabla.csproj -c Release -o /app/build, que en resumen, son comandos de .NET que es para que la app sea productiva y se guarde en /app/build. el 2do comando es dotnet publish -c Release -o /app que lo que hace es que de ese codigo crea un minificado (por que hace los 2? no hacen lo mismo?) Pues si, pero el comando anterior deja una cache y este comando, minifica ese cache y lo hace mucho mejor para que la aplicacion quede mejor productiva y esto se guarda en la carpeta /app. BIEN, ahora entramos en fase 2 o 2do contenedor no tiene nombre, pero digamosle que es final final final... Ahora, el 2do contendor saca el sdk de nuevo, se va a /app y luego hace un COPY, ojo, ahi coloca: COPY --from=build, este comando es para que desde nuestro contendor de fase 1 que le pusimos build EL TOME DESDE ESE CONTENEDOR esto lo hace para que no se confunda y tome nuestro local... Ya que nuestor local no tiene nada, todo eso, lo toma de /app (from) y lo guarda en . BIEN, ahora corremos ENTRYPOINT, que basicamente es LUEGO que montaste el contendor final final, ahora corre este comando, que para resumir es la forma de correr la app en linux de .net Espero que entedieras! No te rindas
Explorando más el funcionamiento del Multi-Stage el ahorro de recursos y los beneficios es acontecido de la siguiente manera: **1.- Etapas:** Segmentar el proceso en capas permite una lectura más fluida. De manera predeterminada cada etapa es inicializada con un identificador numérico empezando en 0, para nombrarlo es empleado "AS" "nombre". **Ejemplo:** [FROM](https://docs.docker.com/reference/dockerfile/#from "Learn more about the FROM instruction") golang:1.23 // Primera Etapa "0" // Serie de Instrucciones FROM scratch // Segunda Etapa COPY --from=**0** // Transferir los elementos de la primera etapa. **Asignando Nombre** [FROM](https://docs.docker.com/reference/dockerfile/#from "Learn more about the FROM instruction") golang:1.23 AS **build** // Primera Etapa "Build" // Serie de Instrucciones FROM scratch // Segunda Etapa COPY --from=**build** // Transferir los elementos de la etapa build. // Serie de Instrucciones **2.- Eliminación Herramientas Redundantes:** Mediante la segmentación de la imagen en etapas permite construir todos los archivos necesarios llamados "artefactos", los cuales pueden ser .exe, ,jar, archivos compilados de C/C++. Para posteriormente transferirlos sin los compiladores o herramientas en caso de no ser necesitados para el despliegue del proyecto aconteciendo de esta manera el ahorro de espacio. Un ejemplo empleado en la documentación oficial de Docker es la creación de un archivo en C donde es compilado y al crear el contendor solamente es ejecutado, por ende es descartado el compilador en la segunda fase al no necesitar compilar más archivos en ejecución. En resumen el Multi-Stage te ayuda a brindar una estructura más sólida de fácil lectura a tu archivo de Docker y descartar las herramientas de construcción que no vas a volver emplear. Para un correcto uso del Multi-Stage se necesita que analices que herramientas sigues necesitando mientras el contenedor sigue en ejecución y descartar aquellas que solo son empleadas para construir archivos esenciales en el tiempo de creación del contenedor. El ejemplo mencionado anteriormente lo puedes recurrir en la documentación oficial de Docker "Multi-stage builds".