mirror of
https://github.com/docker/docs.git
synced 2026-03-27 06:18:55 +07:00
docker github builder docs
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
107
content/manuals/build/ci/github-actions/github-builder/_index.md
Normal file
107
content/manuals/build/ci/github-actions/github-builder/_index.md
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: Docker GitHub Builder
|
||||
linkTitle: GitHub Builder
|
||||
description: Use Docker-maintained reusable GitHub Actions workflows to build images and artifacts with BuildKit.
|
||||
keywords: ci, github actions, gha, buildkit, buildx, bake, reusable workflows
|
||||
params:
|
||||
sidebar:
|
||||
badge:
|
||||
color: green
|
||||
text: New
|
||||
---
|
||||
|
||||
Docker GitHub Builder is a set of [reusable workflows](https://docs.github.com/en/actions/how-tos/reuse-automations/reuse-workflows)
|
||||
in the [`docker/github-builder` repository](https://github.com/docker/github-builder)
|
||||
for building container images and local artifacts with [BuildKit](../../../buildkit/_index.md).
|
||||
This section explains what the workflows solve, how they differ from wiring
|
||||
together individual GitHub Actions in each repository, and when to use
|
||||
[`build.yml`](build.md) or [`bake.yml`](bake.md).
|
||||
|
||||
If you compose a build job from `docker/login-action`, `docker/setup-buildx-action`,
|
||||
`docker/metadata-action`, and either `docker/build-push-action` or
|
||||
`docker/bake-action`, your repository owns every detail of how the build runs.
|
||||
That approach works, but it also means every repository has to maintain its own
|
||||
runner selection, [cache setup](../cache.md), [Provenance settings](../attestations.md),
|
||||
signing behavior, and [multi-platform manifest handling](../multi-platform.md).
|
||||
Docker GitHub Builder moves that implementation into Docker-maintained reusable
|
||||
workflows, so your workflow only decides when to build and which inputs to pass.
|
||||
|
||||
The difference is easiest to see in the job definition. A conventional workflow
|
||||
spells out each action step:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@{{% param "login_action_version" %}}
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@{{% param "setup_qemu_action_version" %}}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@{{% param "setup_buildx_action_version" %}}
|
||||
|
||||
- name: Docker meta
|
||||
uses: docker/metadata-action@{{% param "metadata_action_version" %}}
|
||||
id: meta
|
||||
with:
|
||||
images: name/app
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@{{% param "build_push_action_version" %}}
|
||||
with:
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha
|
||||
```
|
||||
|
||||
With Docker GitHub Builder, the same build is a reusable workflow call:
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: image
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
meta-images: name/app
|
||||
secrets:
|
||||
registry-auths: |
|
||||
- registry: docker.io
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
```
|
||||
|
||||
This model gives you a build pipeline that is maintained in the Docker
|
||||
organization, uses a pinned [BuildKit](../../../buildkit/_index.md) environment,
|
||||
distributes [multi-platform builds](../../../building/multi-platform.md) across
|
||||
runners when that helps, and emits signed [SLSA provenance](../../../metadata/attestations/slsa-provenance.md)
|
||||
that records both the source commit and the builder identity.
|
||||
|
||||
That tradeoff is intentional. You keep control of when the build runs and which
|
||||
inputs it uses, but the build implementation itself lives in the
|
||||
Docker-maintained workflow rather than in per-repository job steps.
|
||||
|
||||
Use [`build.yml`](build.md) when your repository builds from a Dockerfile and
|
||||
the familiar `build-push-action` inputs map cleanly to your workflow. Use
|
||||
[`bake.yml`](bake.md) when your repository already describes builds in a
|
||||
[Bake definition](../../../bake/_index.md), or when you want Bake targets,
|
||||
overrides, and variables to stay as the source of truth.
|
||||
|
||||
Both workflows support image output, local output, cache export to the
|
||||
[GitHub Actions cache backend](../../../cache/backends/gha.md),
|
||||
[SBOM generation](../../../metadata/attestations/sbom.md), and signing. The
|
||||
Bake workflow adds Bake definition validation and builds one target per workflow
|
||||
call.
|
||||
|
||||
{{% sectionlinks %}}
|
||||
146
content/manuals/build/ci/github-actions/github-builder/bake.md
Normal file
146
content/manuals/build/ci/github-actions/github-builder/bake.md
Normal file
@@ -0,0 +1,146 @@
|
||||
---
|
||||
title: Bake with Docker GitHub Builder
|
||||
linkTitle: Bake
|
||||
description: Use the Docker GitHub Builder bake.yml reusable workflow to build images and local artifacts from a Bake definition.
|
||||
keywords: ci, github actions, gha, buildkit, buildx, bake, reusable workflow
|
||||
weight: 20
|
||||
---
|
||||
|
||||
The [`bake.yml` reusable workflow](https://github.com/docker/github-builder?tab=readme-ov-file#bake-reusable-workflow)
|
||||
builds from a [Bake definition](../../../bake/_index.md) instead of a Dockerfile
|
||||
input set. This page shows how to call the workflow for a target, how to pass
|
||||
Bake overrides and variables, and how to export local output when a Bake file
|
||||
is already the source of truth for your build.
|
||||
|
||||
## Build and push a Bake target
|
||||
|
||||
The following workflow builds the `image` target from `docker-bake.hcl` and
|
||||
publishes the result with tags generated from [metadata inputs](../manage-tags-labels.md):
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
tags:
|
||||
- "v*"
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
uses: docker/github-builder/.github/workflows/bake.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: image
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
target: image
|
||||
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 }}
|
||||
```
|
||||
|
||||
Bake workflows build one target per workflow call. Groups and multi-target
|
||||
builds aren't supported because [SLSA provenance](../attestations.md), digest
|
||||
handling, and manifest creation are scoped to a single target.
|
||||
|
||||
The workflow validates the definition before the build starts and resolves
|
||||
the target from the files you pass in `files`.
|
||||
|
||||
## Override target values and variables
|
||||
|
||||
Because the workflow delegates the build to Bake, you can keep using `set` and
|
||||
`vars` for target-specific overrides:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
uses: docker/github-builder/.github/workflows/bake.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: image
|
||||
push: true
|
||||
target: image
|
||||
vars: |
|
||||
IMAGE_TAG=${{ github.sha }}
|
||||
set: |
|
||||
*.args.BUILD_RUN_ID=${{ github.run_id }}
|
||||
*.platform=linux/amd64,linux/arm64
|
||||
cache: true
|
||||
cache-scope: image
|
||||
meta-images: name/app
|
||||
meta-tags: |
|
||||
type=sha
|
||||
set-meta-annotations: true
|
||||
secrets:
|
||||
registry-auths: |
|
||||
- registry: docker.io
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
```
|
||||
|
||||
This form fits repositories that already use Bake groups, target inheritance,
|
||||
and variable expansion. The reusable workflow takes care of Buildx setup,
|
||||
[GitHub Actions cache export](../../../cache/backends/gha.md),
|
||||
[Provenance defaults](../../../metadata/attestations/slsa-provenance.md),
|
||||
signing behavior, and the final multi-platform manifest. Metadata labels and
|
||||
annotations can be merged into the Bake definition without adding a separate
|
||||
metadata step to your workflow.
|
||||
|
||||
## Export local output from Bake
|
||||
|
||||
If the target should export files instead of publishing an image, switch the
|
||||
workflow output to `local` and upload the artifact:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
bake:
|
||||
uses: docker/github-builder/.github/workflows/bake.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: local
|
||||
target: binaries
|
||||
artifact-upload: true
|
||||
artifact-name: bake-output
|
||||
```
|
||||
|
||||
With `output: local`, the workflow injects the matching local output override
|
||||
into the Bake run and merges the uploaded artifacts after the per-platform
|
||||
builds finish. If you need a manual Bake pattern that stays in a normal job,
|
||||
see [Multi-platform image](../multi-platform.md). If your build does not need a
|
||||
Bake definition, use [build.yml](build.md) instead.
|
||||
150
content/manuals/build/ci/github-actions/github-builder/build.md
Normal file
150
content/manuals/build/ci/github-actions/github-builder/build.md
Normal file
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Build with Docker GitHub Builder
|
||||
linkTitle: Build
|
||||
description: Use the Docker GitHub Builder build.yml reusable workflow to build images and local artifacts from a Dockerfile.
|
||||
keywords: ci, github actions, gha, buildkit, buildx, reusable workflow, dockerfile
|
||||
weight: 10
|
||||
---
|
||||
|
||||
The [`build.yml` reusable workflow](https://github.com/docker/github-builder?tab=readme-ov-file#build-reusable-workflow)
|
||||
builds from a Dockerfile and packages the same core tasks that many repositories
|
||||
wire together by hand. This page shows how to call the workflow, publish
|
||||
[multi-platform images](../../../building/multi-platform.md), and export local
|
||||
build artifacts without rebuilding the job structure in every repository.
|
||||
|
||||
## Build and push an image
|
||||
|
||||
The following workflow builds from the repository Dockerfile, pushes on branch
|
||||
and tag events, and uses metadata inputs to generate tags:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
tags:
|
||||
- "v*"
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
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 }}
|
||||
```
|
||||
|
||||
When you set `output: image`, `meta-images` is required because the workflow
|
||||
creates image names and [manifest tags](../manage-tags-labels.md) from that
|
||||
input. `runner: auto` and `distribute: true` are the defaults, so a
|
||||
multi-platform build can fan out across native GitHub-hosted runners instead
|
||||
of forcing the whole build onto one machine. `sign: auto` is also the default,
|
||||
which means the workflow signs [attestation manifests](../attestations.md)
|
||||
when the image is pushed.
|
||||
|
||||
## Export local output as an artifact
|
||||
|
||||
The same workflow can export files instead of publishing an image. This is
|
||||
useful when you want compiled assets, an unpacked root filesystem, or another
|
||||
local exporter result as part of CI:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: local
|
||||
artifact-upload: true
|
||||
artifact-name: build-output
|
||||
platforms: linux/amd64,linux/arm64
|
||||
```
|
||||
|
||||
With `output: local`, the workflow exports files to the runner filesystem and
|
||||
merges per-platform artifacts in the finalize phase. When
|
||||
`artifact-upload: true` is set, the merged result is uploaded as a GitHub
|
||||
artifact, and `sign: auto` signs the uploaded artifacts. `push` is ignored for
|
||||
local output, so there is no registry requirement in this form.
|
||||
|
||||
## Add cache, Dockerfile inputs, and metadata labels
|
||||
|
||||
You can tune the Dockerfile build in the same job call. This example sets a
|
||||
custom Dockerfile path, a target stage, GitHub Actions cache, and metadata
|
||||
labels:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read # to fetch the repository content
|
||||
id-token: write # for signing attestation(s) with GitHub OIDC Token
|
||||
with:
|
||||
output: image
|
||||
push: true
|
||||
context: .
|
||||
file: ./docker/Dockerfile
|
||||
target: runtime
|
||||
build-args: |
|
||||
NODE_ENV=production
|
||||
VERSION=${{ github.sha }}
|
||||
cache: true
|
||||
cache-scope: myapp
|
||||
meta-images: name/app
|
||||
meta-tags: |
|
||||
type=sha
|
||||
set-meta-labels: true
|
||||
secrets:
|
||||
registry-auths: |
|
||||
- registry: docker.io
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
```
|
||||
|
||||
This is a Dockerfile build, so the inputs map closely to
|
||||
`docker/build-push-action`. The difference is that the reusable workflow owns
|
||||
Buildx setup, [BuildKit](../../../buildkit/_index.md) configuration,
|
||||
[SLSA provenance](../../../metadata/attestations/slsa-provenance.md) mode,
|
||||
[GitHub Actions cache backend](../../../cache/backends/gha.md) wiring, signing,
|
||||
and manifest creation. If you need more background on metadata or platform
|
||||
distribution, see [Manage tags and labels](../manage-tags-labels.md) and
|
||||
[Multi-platform image](../multi-platform.md).
|
||||
@@ -102,17 +102,14 @@ jobs:
|
||||
|
||||
Building multiple platforms on the same runner can significantly extend build
|
||||
times, particularly when dealing with complex Dockerfiles or a high number of
|
||||
target platforms. By distributing platform-specific builds across multiple
|
||||
runners using a matrix strategy, you can drastically reduce build durations and
|
||||
streamline your CI pipeline. These examples demonstrate how to allocate each
|
||||
platform build to a dedicated runner, including ARM-native runners where
|
||||
applicable, and create a unified manifest list using the
|
||||
[`buildx imagetools create` command](/reference/cli/docker/buildx/imagetools/create/).
|
||||
target platforms. If you want to split platform builds across multiple runners
|
||||
without maintaining a custom matrix and merge job, use the
|
||||
[Docker GitHub Builder](github-builder/_index.md). The reusable workflows
|
||||
compute the per-platform matrix, run each platform on its own runner, and
|
||||
create the final manifest for you.
|
||||
|
||||
The following workflow will build the image for each platform on a dedicated
|
||||
runner using a matrix strategy and push by digest. Then, the `merge` job will
|
||||
create manifest lists and push them to Docker Hub. The [`metadata` action](https://github.com/docker/metadata-action)
|
||||
is used to set tags and labels.
|
||||
The following workflow uses the [`build.yml` reusable workflow](github-builder/build.md)
|
||||
to distribute a multi-platform Dockerfile build:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
@@ -120,119 +117,43 @@ name: ci
|
||||
on:
|
||||
push:
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: user/app
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@{{% param "metadata_action_version" %}}
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@{{% param "login_action_version" %}}
|
||||
with:
|
||||
uses: docker/github-builder/.github/workflows/build.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
with:
|
||||
output: image
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
meta-images: user/app
|
||||
meta-tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
secrets:
|
||||
registry-auths: |
|
||||
- registry: docker.io
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@{{% param "setup_qemu_action_version" %}}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@{{% param "setup_buildx_action_version" %}}
|
||||
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@{{% param "build_push_action_version" %}}
|
||||
with:
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
tags: ${{ env.REGISTRY_IMAGE }}
|
||||
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@{{% param "login_action_version" %}}
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@{{% param "setup_buildx_action_version" %}}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@{{% param "metadata_action_version" %}}
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||
```
|
||||
|
||||
With `runner: auto` and `distribute: true`, which are the defaults, the
|
||||
workflow splits the build into one platform per runner and assembles the final
|
||||
multi-platform image in its finalize phase. If you need to control the Docker
|
||||
build inputs directly, see [Build with Docker GitHub Builder build.yml](github-builder/build.md).
|
||||
|
||||
### With Bake
|
||||
|
||||
It's also possible to build on multiple runners using Bake, with the
|
||||
[bake action](https://github.com/docker/bake-action).
|
||||
|
||||
You can find a live example [in this GitHub repository](https://github.com/crazy-max/docker-linguist).
|
||||
|
||||
The following example achieves the same results as described in
|
||||
[the previous section](#distribute-build-across-multiple-runners).
|
||||
You can use the [`bake.yml` reusable workflow](github-builder/bake.md) for the
|
||||
same pattern when your build is defined in a Bake file. The workflow reads the
|
||||
target platforms from the Bake definition, distributes the per-platform builds,
|
||||
and publishes the final manifest without a separate prepare or merge job.
|
||||
|
||||
```hcl
|
||||
variable "DEFAULT_TAG" {
|
||||
@@ -275,135 +196,26 @@ name: ci
|
||||
on:
|
||||
push:
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: user/app
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.platforms.outputs.matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
echo "matrix=$(docker buildx bake image-all --print | jq -cr '.target."image-all".platforms')" >>${GITHUB_OUTPUT}
|
||||
|
||||
- name: Show matrix
|
||||
run: |
|
||||
echo ${{ steps.platforms.outputs.matrix }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@{{% param "metadata_action_version" %}}
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
|
||||
- name: Rename meta bake definition file
|
||||
run: |
|
||||
mv "${{ steps.meta.outputs.bake-file }}" "${{ runner.temp }}/bake-meta.json"
|
||||
|
||||
- name: Upload meta bake definition
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bake-meta
|
||||
path: ${{ runner.temp }}/bake-meta.json
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
build:
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.prepare.outputs.matrix) }}
|
||||
runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download meta bake definition
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bake-meta
|
||||
path: ${{ runner.temp }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@{{% param "login_action_version" %}}
|
||||
with:
|
||||
bake:
|
||||
uses: docker/github-builder/.github/workflows/bake.yml@{{% param "github_builder_version" %}}
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
with:
|
||||
output: image
|
||||
push: true
|
||||
target: image-all
|
||||
meta-images: user/app
|
||||
meta-tags: |
|
||||
type=ref,event=branch
|
||||
type=sha
|
||||
secrets:
|
||||
registry-auths: |
|
||||
- registry: docker.io
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@{{% param "setup_buildx_action_version" %}}
|
||||
|
||||
- name: Build
|
||||
id: bake
|
||||
uses: docker/bake-action@{{% param "bake_action_version" %}}
|
||||
with:
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
cwd://${{ runner.temp }}/bake-meta.json
|
||||
targets: image
|
||||
set: |
|
||||
*.tags=${{ env.REGISTRY_IMAGE }}
|
||||
*.platform=${{ matrix.platform }}
|
||||
*.output=type=image,push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ fromJSON(steps.bake.outputs.metadata).image['containerimage.digest'] }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download meta bake definition
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bake-meta
|
||||
path: ${{ runner.temp }}
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@{{% param "login_action_version" %}}
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@{{% param "setup_buildx_action_version" %}}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: ${{ runner.temp }}/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.target."docker-metadata-action".tags | map(select(startswith("${{ env.REGISTRY_IMAGE }}")) | "-t " + .) | join(" ")' ${{ runner.temp }}/bake-meta.json) \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:$(jq -r '.target."docker-metadata-action".args.DOCKER_META_VERSION' ${{ runner.temp }}/bake-meta.json)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user