Compartir comentarios
Las respuestas se generan en base a la documentación.

Arquitectura de Docker GitHub Builder

Docker GitHub Builder separa la orquestación del repositorio de la implementación de la compilación. Un repositorio de consumo decide cuándo se ejecuta una compilación, qué permisos y secretos se conceden, y qué entradas se pasan. El flujo de trabajo reutilizable en el repositorio docker/github-builder es el propietario de la implementación de la compilación en sí. Esa división mantiene los flujos de trabajo de los repositorios cortos a la vez que centraliza BuildKit, el almacenamiento en caché, la procedencia, la generación de SBOM, la firma y el ensamblaje multiplataforma en una única ruta mantenida por Docker.

Vista general de GitHub Builder

Arquitectura principal

Un flujo de trabajo emisor invoca build.yml o bake.yml. build.yml es el punto de entrada para compilaciones orientadas a Dockerfile. bake.yml es el punto de entrada para compilaciones orientadas a Bake, donde la definición de Bake sigue siendo la fuente de verdad para los targets y las anulaciones. En ambos casos, el emisor sigue siendo el propietario de las políticas del repositorio, incluidos los desencadenadores, las condiciones de las ramas, los permisos, los secretos, la selección de targets, las entradas de metadatos y la elección entre la salida de imagen y la salida local.

Dentro del flujo de trabajo reutilizable, la primera fase prepara la compilación. Valida las entradas entrantes, resuelve la configuración del runner y expande una solicitud multiplataforma en un trabajo por plataforma. El modelo de ejecución se puede visualizar como una matriz donde linux/amd64 se ejecuta en ubuntu-24.04 y linux/arm64 se ejecuta en ubuntu-24.04-arm. Cada trabajo de plataforma se compila de forma independiente, y luego el flujo de trabajo finaliza el resultado en un único contrato de salida de cara al emisor.

plataformas solicitadas: linux/amd64,linux/arm64

trabajos de plataforma conceptuales: linux/amd64 -> ubuntu-24.04
  linux/arm64 -> ubuntu-24.04-arm

Selección de runners

La entrada runner acepta una única etiqueta de runner de Linux alojado en GitHub o una asignación de plataformas delimitada por saltos de línea.

El valor predeterminado es una asignación de plataformas que utiliza runners de Ubuntu alojados en GitHub:

runner: |
  default=ubuntu-24.04
  linux/arm=ubuntu-24.04-arm
  linux/arm64=ubuntu-24.04-arm

En el trabajo de plataforma, la etiqueta del runner se resuelve en un único valor:

runner: ubuntu-24.04

Una asignación debe definir un runner default. Las otras claves son prefijos de plataforma, y el prefijo coincidente más específico tiene prioridad. Por ejemplo, linux/arm coincide con variantes como linux/arm/v7, mientras que linux/arm64 es un prefijo independiente.

En el siguiente ejemplo, linux coincide con plataformas Linux que no coinciden con un prefijo más largo. La clave default sigue siendo requerida porque es la opción de respaldo cuando ningún prefijo de plataforma coincide.

runner: |
  default=ubuntu-24.04
  linux=ubuntu-24.04
  linux/arm=ubuntu-24.04-arm
  linux/arm64=ubuntu-24.04-arm

Los flujos de trabajo reutilizables requieren runners de Linux alojados en GitHub. Los valores heredados auto, amd64 y arm64 se siguen aceptando por compatibilidad, pero emiten advertencias de obsolescencia. Utiliza en su lugar una etiqueta de runner explícita o una asignación de plataformas.

Ruta de ejecución

Flujo de ejecución de GitHub Builder

La ruta de ejecución se mantiene corta a propósito. El repositorio de consumo llama al flujo de trabajo reutilizable. El flujo de trabajo reutilizable prepara la compilación, ejecuta los trabajos por plataforma y finaliza el resultado. Para la salida de imágenes, la finalización produce una imagen de registro y un manifiesto multiplataforma. Para la salida local, la finalización fusiona los archivos de cada plataforma y puede subir el resultado fusionado como un artefacto de GitHub. El emisor no necesita reconstruir cómo se conectaron Buildx, BuildKit, el almacenamiento en caché o el ensamblaje del manifiesto.

Los dos puntos de entrada reutilizables

build.yml se adapta mejor cuando la compilación ya está expresada como un flujo de trabajo orientado a Dockerfile. Se alinea de forma natural con conceptos como context, file, target, build-args, labels, annotations y platforms. Este es el punto de entrada que se siente más cercano a docker/build-push-action, excepto que la implementación del flujo de trabajo está centralizada.

bake.yml se adapta mejor cuando el repositorio ya utiliza Bake como definición de compilación. Preserva el modelo de Bake, incluida la resolución de targets, files, set y vars, al tiempo que enruta la ejecución a través de la misma ruta de compilación mantenida por Docker. Un detalle arquitectónico importante es que el flujo de trabajo de Bake se centra en un target por llamada de flujo de trabajo, lo que mantiene la procedencia, el manejo de resúmenes (digests) y el ensamblaje final del manifiesto limitados a una unidad de compilación a la vez.

Modelo de salida

Los flujos de trabajo reutilizables exponen un conjunto estable de salidas de cara al emisor para que los trabajos posteriores puedan consumir los resultados sin comprender el gráfico de trabajos internos. En la práctica, los valores principales son digest, meta-json, artifact-name, output-type y signed. Ese contrato es importante porque mantiene la promoción, publicación o automatización posterior desacoplada de la mecánica de selección de runners y el ensamblaje por plataforma.

Ejemplos

Compilación de imagen orientada a Dockerfile

El siguiente ejemplo muestra la forma de una compilación de imagen multiplataforma impulsada por build.yml.

name: ci

on:
  push:
    branches:
      - "main"
    tags:
      - "v*"
  pull_request:

permissions:
  contents: read

jobs:
  build:
    uses: docker/github-builder/.github/workflows/build.yml@v1
    permissions:
      contents: read
      id-token: write
    with:
      output: image
      push: ${{ github.event_name != 'pull_request' }}
      platforms: linux/amd64,linux/arm64
      meta-images: name/app
      meta-tags: |
        type=ref,event=branch
        type=ref,event=pr
        type=semver,pattern={{version}}
    secrets:
      registry-auths: |
        - registry: docker.io
          username: ${{ vars.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

Esta llamada es pequeña porque el flujo de trabajo reutilizable se encarga del trabajo pesado. El repositorio decide cuándo debe ejecutarse la compilación y qué entradas desea, mientras que la implementación compartida maneja la configuración de Buildx, la configuración de BuildKit, la distribución por plataformas (platform fan-out), la generación de metadatos, la procedencia, la generación de SBOM, la firma y la creación del manifiesto final.

Salida local orientada a Bake

El siguiente ejemplo muestra la forma de una llamada de Bake que exporta salida local y sube el artefacto fusionado.

name: ci

on:
  pull_request:

permissions:
  contents: read

jobs:
  bake:
    uses: docker/github-builder/.github/workflows/bake.yml@v1
    permissions:
      contents: read
      id-token: write
    with:
      output: local
      target: binaries
      artifact-upload: true
      artifact-name: bake-output

Esta forma es útil cuando el repositorio ya mantiene su definición de compilación en Bake y desea preservar esa fuente de verdad. El flujo de trabajo inyecta el comportamiento de salida local en la ejecución de Bake, ejecuta el target por plataforma cuando es necesario y fusiona el resultado en un único artefacto de cara al emisor.

Por qué funciona esta arquitectura

Rendimiento

La mejora de rendimiento proviene de la distribución nativa por plataformas (platform fan-out), la configuración compartida de BuildKit y el manejo centralizado de la caché. El trabajo multiplataforma se puede distribuir en runners compatibles alojados en GitHub en lugar de forzar a cada arquitectura a ejecutarse en una sola máquina de compilación. Esto reduce la presión de emulación, acorta la ruta crítica para compilaciones multiplataforma y proporciona a cada repositorio de consumo la misma línea base de compilación optimizada.

Seguridad

El modelo de seguridad proviene de colocar la implementación de la compilación en flujos de trabajo reutilizables mantenidos por Docker en lugar de pasos de trabajo ad hoc en cada repositorio de consumo. El emisor sigue controlando los permisos y los secretos, pero la lógica de compilación en sí misma se revisa y versiona de forma centralizada. El proyecto también trata la procedencia, la generación de SBOM y la firma como aspectos de primer nivel, lo que fortalece el límite de confianza entre la orquestación del repositorio y la producción de artefactos.

Aislamiento y confiabilidad

La confiabilidad proviene de la separación de conceptos. El repositorio de consumo orquesta la compilación. El flujo de trabajo reutilizable ejecuta la compilación. Esto reduce la desviación de CI (CI drift), elimina el código repetitivo de integración de los repositorios y hace que el resultado sea más fácil de razonar porque el emisor ve un contrato estable en lugar de una gran definición de trabajo personalizada.