Skip to content

Commit af656d8

Browse files
committed
Build multi-arch images natively instead of with QEMU
Replace QEMU emulation with native runners for amd64 and arm64 builds. Each platform builds in parallel, uploads its digest as an artifact, and a final merge job combines them into a single multi-arch manifest.
1 parent 843a6ad commit af656d8

File tree

1 file changed

+70
-13
lines changed

1 file changed

+70
-13
lines changed

.github/workflows/release-image.yml

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,16 @@ on:
99
- image/**
1010

1111
jobs:
12-
build-and-push:
13-
runs-on: ubuntu-latest
12+
build:
13+
strategy:
14+
matrix:
15+
include:
16+
- platform: linux/amd64
17+
runner: ubuntu-latest
18+
- platform: linux/arm64
19+
runner: ubuntu-24.04-arm
20+
21+
runs-on: ${{ matrix.runner }}
1422
permissions:
1523
contents: read
1624
packages: write
@@ -26,20 +34,69 @@ jobs:
2634
username: ${{ github.actor }}
2735
password: ${{ secrets.GITHUB_TOKEN }}
2836

29-
- name: Set up QEMU
30-
uses: docker/setup-qemu-action@v3
31-
3237
- name: Set up Docker Buildx
3338
uses: docker/setup-buildx-action@v3
3439

35-
- name: Build and push
40+
- name: Docker metadata
41+
id: meta
42+
uses: docker/metadata-action@v5
43+
with:
44+
images: ghcr.io/${{ github.repository_owner }}/devcontainer
45+
46+
- name: Build and push by digest
47+
id: build
3648
uses: docker/build-push-action@v6
3749
with:
3850
context: ./image
39-
platforms: linux/amd64,linux/arm64
40-
push: true
41-
tags: |
42-
ghcr.io/${{ github.repository_owner }}/devcontainer:latest
43-
ghcr.io/${{ github.repository_owner }}/devcontainer:${{ github.sha }}
44-
cache-from: type=gha
45-
cache-to: type=gha,mode=max
51+
platforms: ${{ matrix.platform }}
52+
labels: ${{ steps.meta.outputs.labels }}
53+
outputs: type=image,name=ghcr.io/${{ github.repository_owner }}/devcontainer,push-by-digest=true,name-canonical=true,push=true
54+
cache-from: type=gha,scope=${{ matrix.platform }}
55+
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
56+
57+
- name: Export digest
58+
run: |
59+
mkdir -p ${{ runner.temp }}/digests
60+
digest="${{ steps.build.outputs.digest }}"
61+
touch "${{ runner.temp }}/digests/${digest#sha256:}"
62+
63+
- name: Upload digest
64+
uses: actions/upload-artifact@v4
65+
with:
66+
name: digests-${{ matrix.runner }}
67+
path: ${{ runner.temp }}/digests/*
68+
if-no-files-found: error
69+
retention-days: 1
70+
71+
merge:
72+
runs-on: ubuntu-latest
73+
needs: build
74+
permissions:
75+
contents: read
76+
packages: write
77+
78+
steps:
79+
- name: Download digests
80+
uses: actions/download-artifact@v4
81+
with:
82+
path: ${{ runner.temp }}/digests
83+
pattern: digests-*
84+
merge-multiple: true
85+
86+
- name: Log in to GitHub Container Registry
87+
uses: docker/login-action@v3
88+
with:
89+
registry: ghcr.io
90+
username: ${{ github.actor }}
91+
password: ${{ secrets.GITHUB_TOKEN }}
92+
93+
- name: Set up Docker Buildx
94+
uses: docker/setup-buildx-action@v3
95+
96+
- name: Create and push manifest
97+
working-directory: ${{ runner.temp }}/digests
98+
run: |
99+
docker buildx imagetools create \
100+
-t ghcr.io/${{ github.repository_owner }}/devcontainer:latest \
101+
-t ghcr.io/${{ github.repository_owner }}/devcontainer:${{ github.sha }} \
102+
$(printf 'ghcr.io/${{ github.repository_owner }}/devcontainer@sha256:%s ' *)

0 commit comments

Comments
 (0)