1+ # Inspired by https://github.com/sredevopsorg/multi-arch-docker-github-workflow
12name : Docker Image CI
23
34on :
1112 required : false
1213
1314jobs :
14- build-and-push :
15- runs-on : ubuntu-latest
15+ build :
16+ runs-on : ${{ matrix.runner }}
1617
1718 permissions :
1819 contents : read
1920 packages : write
2021
22+ strategy :
23+ fail-fast : false
24+ matrix :
25+ include :
26+ - platform : linux/amd64
27+ runner : ubuntu-latest
28+ - platform : linux/arm64
29+ runner : ubuntu-24.04-arm
30+
2131 steps :
2232 - name : Checkout code
2333 uses : actions/checkout@v6
3242 username : ${{ github.actor }}
3343 password : ${{ secrets.GITHUB_TOKEN }}
3444
35- - name : Set up QEMU
36- uses : docker/setup-qemu-action@v4
37-
3845 - name : Set up Docker Buildx
3946 uses : docker/setup-buildx-action@v4
4047
@@ -55,13 +62,100 @@ jobs:
5562 type=raw,value=latest
5663 type=raw,value=${{ steps.tag.outputs.value }},enable=${{ inputs.upstream_tag != '' }}
5764
58- - name : Build and push
65+ - name : Build and push by digest
66+ id : build
5967 uses : docker/build-push-action@v7
6068 with :
6169 context : .
62- push : true
63- platforms : linux/amd64,linux/arm64
64- tags : ${{ steps.meta.outputs.tags }}
70+ platforms : ${{ matrix.platform }}
6571 labels : ${{ steps.meta.outputs.labels }}
66- cache-from : type=gha
67- cache-to : type=gha,mode=max
72+ outputs : type=image,name=ghcr.io/${{ github.repository }},push-by-digest=true,name-canonical=true,push=true
73+ cache-from : type=gha,scope=${{ matrix.platform }}
74+ cache-to : type=gha,mode=max,scope=${{ matrix.platform }}
75+
76+ - name : Export digest
77+ run : |
78+ mkdir -p /tmp/digests
79+ touch "/tmp/digests/${DIGEST#sha256:}"
80+ env :
81+ DIGEST : ${{ steps.build.outputs.digest }}
82+
83+ - name : Upload digest
84+ uses : actions/upload-artifact@v4
85+ with :
86+ name : digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
87+ path : /tmp/digests/*
88+ if-no-files-found : error
89+ retention-days : 1
90+
91+ merge :
92+ runs-on : ubuntu-latest
93+ needs : build
94+
95+ permissions :
96+ contents : read
97+ packages : write
98+
99+ steps :
100+ - name : Download digests
101+ uses : actions/download-artifact@v4
102+ with :
103+ path : /tmp/digests
104+ pattern : digests-*
105+ merge-multiple : true
106+
107+ - name : Log in to GitHub Packages
108+ uses : docker/login-action@v4
109+ with :
110+ registry : ghcr.io
111+ username : ${{ github.actor }}
112+ password : ${{ secrets.GITHUB_TOKEN }}
113+
114+ - name : Set up Docker Buildx
115+ uses : docker/setup-buildx-action@v4
116+
117+ - name : Sanitize upstream tag
118+ if : inputs.upstream_tag != ''
119+ id : tag
120+ run : echo "value=${INPUT_TAG#v}" >> $GITHUB_OUTPUT
121+ env :
122+ INPUT_TAG : ${{ inputs.upstream_tag }}
123+
124+ - name : Extract metadata
125+ id : meta
126+ uses : docker/metadata-action@v6
127+ with :
128+ images : ghcr.io/${{ github.repository }}
129+ tags : |
130+ type=ref,event=tag
131+ type=raw,value=latest
132+ type=raw,value=${{ steps.tag.outputs.value }},enable=${{ inputs.upstream_tag != '' }}
133+
134+ - name : Get timestamp
135+ id : timestamp
136+ run : echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
137+
138+ - name : Create and push manifest
139+ id : manifest
140+ working-directory : /tmp/digests
141+ continue-on-error : true
142+ run : |
143+ docker buildx imagetools create \
144+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
145+ --annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
146+ --annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
147+ --annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
148+ --annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
149+ $(printf 'ghcr.io/${{ github.repository }}@sha256:%s ' *)
150+
151+ - name : Create and push manifest (without annotations)
152+ if : steps.manifest.outcome == 'failure'
153+ working-directory : /tmp/digests
154+ run : |
155+ docker buildx imagetools create \
156+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
157+ $(printf 'ghcr.io/${{ github.repository }}@sha256:%s ' *)
158+
159+ - name : Inspect manifest
160+ run : |
161+ docker buildx imagetools inspect 'ghcr.io/${{ github.repository }}:${{ steps.meta.outputs.version }}'
0 commit comments