# BuildKit


[BuildKit](https://github.com/moby/buildkit) es el backend de compilación (builder backend) utilizado por
Docker. BuildKit proporciona una funcionalidad mejorada y mejora el rendimiento de tus
compilaciones en comparación con el builder heredado utilizado en versiones anteriores de Docker. También
introduce soporte para manejar escenarios más complejos:

- Detectar y omitir la ejecución de etapas de compilación no utilizadas
- Paralelizar la compilación de etapas de compilación independientes
- Transferir de forma incremental solo los archivos modificados en tu
  [contexto de compilación](/concepts/context/) entre compilaciones
- Detectar y omitir la transferencia de archivos no utilizados en tu
  [contexto de compilación](/concepts/context/)
- Utilizar implementaciones de [frontend de Dockerfile](/build/buildkit/frontend/) con muchas
  características adicionales
- Evitar efectos secundarios con el resto de la API (imágenes y contenedores intermedios)
- Priorizar tu caché de compilación para la limpieza automática (pruning)

Las principales áreas en las que BuildKit mejora con respecto al builder heredado son el rendimiento, la gestión del
almacenamiento y la extensibilidad. Desde el lado del rendimiento, una actualización significativa
es un solucionador de gráficos de compilación completamente concurrente. Puede ejecutar pasos de compilación en paralelo cuando sea posible y optimizar
comandos que no tienen impacto en el resultado final.
El acceso a los archivos fuente locales también se ha optimizado. Al realizar un seguimiento
únicamente de las actualizaciones realizadas en estos archivos entre invocaciones de compilación repetidas,
no es necesario esperar a que se lean o suban los archivos locales antes de poder comenzar el trabajo.

## LLB

En el núcleo de BuildKit se encuentra un formato de definición de
[Compilación de Bajo Nivel (LLB, Low-Level Build)](https://github.com/moby/buildkit#exploring-llb). LLB es un formato binario intermedio
que permite a los desarrolladores extender BuildKit. LLB define un gráfico de dependencias
direccionable por contenido que se puede utilizar para componer definiciones de compilación
complejas. También admite características que no están expuestas en los Dockerfiles, como el montaje directo
de datos y la invocación anidada.

<figure class="invertible"><img src="../images/buildkit-dag.svg">
</figure>


Todo lo relacionado con la ejecución y el almacenamiento en caché de tus compilaciones se define en LLB. El
modelo de almacenamiento en caché se ha rediseñado por completo en comparación con el builder heredado. En lugar de
utilizar heurísticas para comparar imágenes, LLB realiza un seguimiento directo de las sumas de verificación (checksums) de los gráficos de compilación
y del contenido montado en operaciones específicas. Esto lo hace mucho más rápido,
más preciso y portátil. El caché de compilación se puede incluso exportar a un registro,
desde donde puede ser descargado bajo demanda por invocaciones posteriores en cualquier host.

LLB se puede generar directamente utilizando un
[paquete de cliente en Go](https://pkg.go.dev/github.com/moby/buildkit/client/llb) que permite definir las relaciones entre tus
operaciones de compilación utilizando primitivas del lenguaje Go. Esto te brinda total poder para ejecutar
cualquier cosa que puedas imaginar, pero probablemente no sea la forma en que la mayoría de las personas definirán
sus compilaciones. En su lugar, la mayoría de los usuarios utilizarían un componente frontend, o una invocación anidada de LLB,
para ejecutar un conjunto preparado de pasos de compilación.

## Frontend

Un frontend es un componente que toma un formato de compilación legible por humanos y lo convierte
en LLB para que BuildKit pueda ejecutarlo. Los frontends se pueden distribuir como imágenes,
y el usuario puede apuntar a una versión específica de un frontend que se garantiza que
funcionará con las características utilizadas por su definición.

Por ejemplo, para compilar un [Dockerfile](/reference/dockerfile/) con
BuildKit, deberías
[utilizar un frontend de Dockerfile externo](/build/buildkit/frontend/).

## Primeros pasos

BuildKit es el builder predeterminado para los usuarios de Docker Desktop y Docker Engine.
Si estás compilando contenedores de Windows, en su lugar se utiliza el builder heredado.

## BuildKit en Windows

> [!WARNING]
>
> BuildKit solo admite de forma completa la compilación de contenedores Linux. El soporte para
> contenedores de Windows es experimental.

BuildKit tiene soporte experimental para contenedores de Windows (WCOW) a partir de la versión 0.13.
Esta sección te guía a través de los pasos para probarlo.
Para compartir comentarios, [abre un problema en el repositorio](https://github.com/moby/buildkit/issues/new), especialmente sobre `buildkitd.exe`.

### Limitaciones conocidas

Para obtener información sobre errores abiertos y limitaciones relacionadas con BuildKit en Windows,
consulta los [problemas de GitHub](https://github.com/moby/buildkit/issues?q=is%3Aissue%20state%3Aopen%20label%3Aarea%2Fwindows-wcow).

### Requisitos previos

- Arquitectura: `amd64`, `arm64` (binarios disponibles pero no probados oficialmente aún).
- SO admitido: Windows Server 2019, Windows Server 2022, Windows 11.
- Imágenes base: `ServerCore:ltsc2019`, `ServerCore:ltsc2022`, `NanoServer:ltsc2022`.
  Consulta el [mapa de compatibilidad aquí](https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2019%2Cwindows-11#windows-server-host-os-compatibility).
- Docker Desktop versión 4.29 o posterior

### Pasos

> [!NOTE]
>
> Los siguientes comandos requieren privilegios de administrador (elevados) en una terminal de PowerShell.

1. Habilita las características de Windows **Hyper-V** y **Containers**.

   ```console
   > Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V, Containers -All
   ```

   Si ves `RestartNeeded` como `True`, reinicia tu máquina y vuelve a abrir una terminal de PowerShell como administrador.
   De lo contrario, continúa con el siguiente paso.

2. Cambia a contenedores de Windows en Docker Desktop.

   Selecciona el icono de Docker en la barra de tareas y luego **Switch to Windows containers...** (Cambiar a contenedores de Windows...).

3. Instala containerd versión 1.7.7 o posterior siguiendo las [instrucciones de configuración](https://github.com/containerd/containerd/blob/main/docs/getting-started.md#installing-containerd-on-windows).

4. Descarga y extrae la última versión de BuildKit.

   ```powershell
   $version = "v0.22.0" # especifica la versión del lanzamiento, v0.13+
   $arch = "amd64" # binario arm64 disponible también
   curl.exe -LO https://github.com/moby/buildkit/releases/download/$version/buildkit-$version.windows-$arch.tar.gz
   # podría haber otro directorio `.\bin` de las instrucciones de containerd
   # puedes moverlos
   mv bin bin2
   tar.exe xvf .\buildkit-$version.windows-$arch.tar.gz
   ## x bin/
   ## x bin/buildctl.exe
   ## x bin/buildkitd.exe
   ```

5. Instala los binarios de BuildKit en la variable `PATH`.

   ```powershell
   # después de que los binarios se extraigan en el directorio bin
   # muévelos a una ruta adecuada en tus directorios de $Env:PATH o:
   Copy-Item -Path ".\bin" -Destination "$Env:ProgramFiles\buildkit" -Recurse -Force
   # añade los binarios `buildkitd.exe` y `buildctl.exe` en la variable $Env:PATH
   $Path = [Environment]::GetEnvironmentVariable("PATH", "Machine") + `
       [IO.Path]::PathSeparator + "$Env:ProgramFiles\buildkit"
   [Environment]::SetEnvironmentVariable( "Path", $Path, "Machine")
   $Env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + `
       [System.Environment]::GetEnvironmentVariable("Path","User")
   ```

6. Inicia el demonio de BuildKit.

   ```console
   > buildkitd.exe
   ```

   > [!NOTE]
   > Si estás ejecutando un proceso `containerd` _gestionado por dockerd_, úsalo en su lugar suministrando la dirección:
   > `buildkitd.exe --containerd-worker-addr "npipe:////./pipe/docker-containerd"`

7. Inicia otra terminal con privilegios de administrador y crea un builder remoto que utilice el demonio de BuildKit local.

   > [!NOTE]
   >
   > Esto requiere Docker Desktop versión 4.29 o posterior.

   ```console
   > docker buildx create --name buildkit-exp --use --driver=remote npipe:////./pipe/buildkitd
   buildkit-exp
   ```

8. Verifica la conexión con el builder ejecutando `docker buildx inspect`.

   ```console
   > docker buildx inspect
   ```

   La salida debe indicar que la plataforma del builder es Windows,
   y que el extremo (endpoint) del builder es una tubería nombrada (named pipe).

   ```text
   Name:          buildkit-exp
    Driver:        remote
    Last Activity: 2024-04-15 17:51:58 +0000 UTC
    Nodes:
    Name:             buildkit-exp0
    Endpoint:         npipe:////./pipe/buildkitd
    Status:           running
    BuildKit version: v0.13.1
    Platforms:        windows/amd64
   ...
   ```

9. Crea un Dockerfile y compila una imagen `hello-buildkit`.

   ```console
   > mkdir sample_dockerfile
   > cd sample_dockerfile
   > Set-Content Dockerfile @"
   FROM mcr.microsoft.com/windows/nanoserver:ltsc2022
   USER ContainerAdministrator
   COPY hello.txt C:/
   RUN echo "Goodbye!" >> hello.txt
   CMD ["cmd", "/C", "type C:\\hello.txt"]
   "@
   Set-Content hello.txt @"
   Hello from BuildKit!
   This message shows that your installation appears to be working correctly.
   "@
   ```

10. Compila y sube (push) la imagen a un registro.

    ```console
    > docker buildx build --push -t <username>/hello-buildkit .
    ```

11. Después de subirla al registro, ejecuta la imagen con `docker run`.

    ```console
    > docker run <username>/hello-buildkit
    ```


