Skip to content

Commit 8adfb60

Browse files
authored
Merge pull request #24604 from crazy-max/github-builder-arch
github builder architecture
2 parents f05365b + 5e05df4 commit 8adfb60

File tree

5 files changed

+194
-4
lines changed

5 files changed

+194
-4
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
---
2+
title: Docker GitHub Builder architecture
3+
linkTitle: Architecture
4+
description: Learn about the architecture of Docker GitHub Builder, a set of reusable workflows for building images and artifacts with BuildKit in GitHub Actions.
5+
keywords: ci, github actions, gha, buildkit, buildx, bake, reusable workflows
6+
weight: 10
7+
---
8+
9+
Docker GitHub Builder separates repository orchestration from build
10+
implementation. A consuming repository decides when a build runs, which
11+
permissions and secrets are granted, and which inputs are passed. The reusable
12+
workflow in [`docker/github-builder` repository](https://github.com/docker/github-builder)
13+
owns the build implementation itself. That split keeps repository workflows
14+
short while centralizing BuildKit, caching, provenance, SBOM generation,
15+
signing, and multi-platform assembly in one Docker-maintained path.
16+
17+
![GitHub Builder overview](./images/architecture-overview.png)
18+
19+
## Core architecture
20+
21+
A caller workflow invokes either [`build.yml`](build.md) or [`bake.yml`](bake.md).
22+
[`build.yml`](build.md) is the entrypoint for Dockerfile-oriented builds.
23+
[`bake.yml`](bake.md) is the entrypoint for Bake-oriented builds, where the
24+
Bake definition remains the source of truth for targets and overrides. In both
25+
cases the caller still owns repository policy, including triggers, branch
26+
conditions, permissions, secrets, target selection, metadata inputs, and the
27+
choice between image output and local output.
28+
29+
Inside the reusable workflow, the first phase prepares the build. It validates
30+
the incoming inputs, resolves the appropriate runner, and expands a
31+
multi-platform request into one job per platform. The execution model is
32+
easiest to picture as a matrix where `linux/amd64` runs on `ubuntu-24.04` and
33+
`linux/arm64` runs on `ubuntu-24.04-arm`. Each platform job builds independently,
34+
then the workflow finalizes the result into one caller-facing output contract.
35+
36+
```yaml
37+
requested platforms:
38+
linux/amd64,linux/arm64
39+
40+
conceptual platform jobs:
41+
linux/amd64 -> ubuntu-24.04
42+
linux/arm64 -> ubuntu-24.04-arm
43+
```
44+
45+
## Execution path
46+
47+
![GitHub Builder execution flow](./images/execution-flow.png)
48+
49+
The execution path stays short on purpose. The consuming repository calls the
50+
reusable workflow. The reusable workflow prepares the build, runs the
51+
per-platform jobs, and finalizes the result. For image output, finalization
52+
produces a registry image and multi-platform manifest. For local output,
53+
finalization merges the per-platform files and can upload the merged result as
54+
a GitHub artifact. The caller does not need to reconstruct how Buildx,
55+
BuildKit, caching, or manifest assembly were wired together.
56+
57+
## The two reusable entrypoints
58+
59+
[`build.yml`](build.md) is the better fit when the build is already expressed as
60+
a Dockerfile-oriented workflow. It lines up naturally with concepts such as
61+
`context`, `file`, `target`, `build-args`, `labels`, `annotations`, and
62+
`platforms`. This is the entrypoint that feels closest to
63+
`docker/build-push-action`, except the workflow implementation is centralized.
64+
65+
[`bake.yml`](bake.md) is the better fit when the repository already uses Bake
66+
as the build definition. It preserves the Bake model, including target
67+
resolution, `files`, `set`, and `vars`, while still routing execution through
68+
the same Docker-maintained build path. One important architectural detail is
69+
that the Bake workflow is centered on one target per workflow call, which keeps
70+
provenance, digest handling, and final manifest assembly scoped to one build
71+
unit at a time.
72+
73+
## Output model
74+
75+
The reusable workflows expose a stable set of caller-facing outputs so
76+
downstream jobs can consume results without understanding the internal job
77+
graph. In practice, the main values are `digest`, `meta-json`, `artifact-name`,
78+
`output-type`, and `signed`. That contract matters because it keeps promotion,
79+
publishing, or follow-on automation decoupled from the mechanics of runner
80+
selection and per-platform assembly.
81+
82+
## Examples
83+
84+
### Dockerfile-oriented image build
85+
86+
The following example shows the shape of a multi-platform image build driven
87+
by [`build.yml`](build.md).
88+
89+
```yaml
90+
name: ci
91+
92+
on:
93+
push:
94+
branches:
95+
- "main"
96+
tags:
97+
- "v*"
98+
pull_request:
99+
100+
permissions:
101+
contents: read
102+
103+
jobs:
104+
build:
105+
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
106+
permissions:
107+
contents: read
108+
id-token: write
109+
with:
110+
output: image
111+
push: ${{ github.event_name != 'pull_request' }}
112+
platforms: linux/amd64,linux/arm64
113+
meta-images: name/app
114+
meta-tags: |
115+
type=ref,event=branch
116+
type=ref,event=pr
117+
type=semver,pattern={{version}}
118+
secrets:
119+
registry-auths: |
120+
- registry: docker.io
121+
username: ${{ vars.DOCKERHUB_USERNAME }}
122+
password: ${{ secrets.DOCKERHUB_TOKEN }}
123+
```
124+
125+
This call is small because the reusable workflow absorbs the heavy lifting. The
126+
repository decides when the build should run and which inputs it wants, while
127+
the shared implementation handles Buildx setup, BuildKit configuration,
128+
platform fan-out, metadata generation, provenance, SBOM generation, signing,
129+
and final manifest creation.
130+
131+
### Bake-oriented local output
132+
133+
The following example shows the shape of a Bake call that exports local output
134+
and uploads the merged artifact.
135+
136+
```yaml
137+
name: ci
138+
139+
on:
140+
pull_request:
141+
142+
permissions:
143+
contents: read
144+
145+
jobs:
146+
bake:
147+
uses: docker/github-builder/.github/workflows/bake.yml@{{% param "github_builder_version" %}}
148+
permissions:
149+
contents: read
150+
id-token: write
151+
with:
152+
output: local
153+
target: binaries
154+
artifact-upload: true
155+
artifact-name: bake-output
156+
```
157+
158+
This form is useful when the repository already keeps its build definition in
159+
Bake and wants to preserve that source of truth. The workflow injects the local
160+
output behavior into the Bake run, executes the target per platform when
161+
needed, and merges the result into one caller-facing artifact.
162+
163+
## Why this architecture works
164+
165+
### Performance
166+
167+
The performance story comes from native platform fan-out, shared BuildKit
168+
configuration, and centralized cache handling. Multi-platform work can be
169+
spread across matching GitHub-hosted runners instead of forcing every
170+
architecture through one build machine. That reduces emulation pressure,
171+
shortens the critical path for cross-platform builds, and gives every
172+
consuming repository the same optimized build baseline.
173+
174+
### Security
175+
176+
The security model comes from putting the build implementation in
177+
Docker-maintained reusable workflows instead of ad hoc job steps in each
178+
consumer repository. The caller still controls permissions and secrets, but
179+
the build logic itself is centrally reviewed and versioned. The project also
180+
treats provenance, SBOM generation, and signing as first-class concerns,
181+
which strengthens the trust boundary between repository orchestration and
182+
artifact production.
183+
184+
### Isolation and reliability
185+
186+
The reliability story comes from separation of concerns. The consuming
187+
repository orchestrates the build. The reusable workflow executes the build.
188+
That reduces CI drift, removes repeated glue code from repositories, and makes
189+
the outcome easier to reason about because the caller sees a stable contract
190+
instead of a large custom job definition.

content/manuals/build/ci/github-actions/github-builder/bake.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
title: Bake with Docker GitHub Builder
3-
linkTitle: Bake
3+
linkTitle: Bake workflow
44
description: Use the Docker GitHub Builder bake.yml reusable workflow to build images and local artifacts from a Bake definition.
55
keywords: ci, github actions, gha, buildkit, buildx, bake, reusable workflow
6-
weight: 20
6+
weight: 30
77
---
88

99
The [`bake.yml` reusable workflow](https://github.com/docker/github-builder?tab=readme-ov-file#bake-reusable-workflow)

content/manuals/build/ci/github-actions/github-builder/build.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
title: Build with Docker GitHub Builder
3-
linkTitle: Build
3+
linkTitle: Build workflow
44
description: Use the Docker GitHub Builder build.yml reusable workflow to build images and local artifacts from a Dockerfile.
55
keywords: ci, github actions, gha, buildkit, buildx, reusable workflow, dockerfile
6-
weight: 10
6+
weight: 20
77
---
88

99
The [`build.yml` reusable workflow](https://github.com/docker/github-builder?tab=readme-ov-file#build-reusable-workflow)
54 KB
Loading
42.8 KB
Loading

0 commit comments

Comments
 (0)