@@ -203,14 +203,24 @@ jobs:
203203 retention-days : 30
204204
205205 # ============================================
206- # Docker 构建(仅 tag push)
206+ # Docker 构建(仅 tag push,原生双架构并行构建后合并多架构 Manifest )
207207 # ============================================
208- docker-build :
209- runs-on : ubuntu-latest
210- name : Docker Build & Push
208+ docker-build-arch :
209+ name : Docker Build (${{ matrix.arch }})
211210 # 只在 tag 推送时构建镜像,且须先通过公开历史检查
212211 needs : publication-check
213212 if : startsWith(github.ref, 'refs/tags/')
213+ strategy :
214+ fail-fast : false
215+ matrix :
216+ include :
217+ - arch : amd64
218+ platform : linux/amd64
219+ os : ubuntu-24.04
220+ - arch : arm64
221+ platform : linux/arm64
222+ os : ubuntu-24.04-arm
223+ runs-on : ${{ matrix.os }}
214224 permissions :
215225 contents : read
216226 packages : write
@@ -238,23 +248,96 @@ jobs:
238248 type=raw,value=latest,enable=${{ !contains(github.ref, '-') }}
239249 type=sha,prefix=sha-
240250
241- - name : Set up QEMU (Enable multi-arch)
242- uses : docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
243-
244251 - name : Set up Docker Buildx
245252 uses : docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
246253
247- - name : Build and push Docker image
254+ - name : Build and push Docker image by digest
255+ id : build
248256 uses : docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
249257 with :
250258 context : .
251- push : true
252- platforms : linux/amd64,linux/arm64
253- tags : ${{ steps.meta.outputs.tags }}
259+ platforms : ${{ matrix.platform }}
254260 labels : ${{ steps.meta.outputs.labels }}
255261 build-args : |
256262 APP_VERSION=${{ steps.meta.outputs.version }}
257263 APP_REVISION=${{ github.sha }}
258- TEST_TIMEOUT_MS=120000
259- cache-from : type=gha
260- cache-to : type=gha,mode=max
264+ outputs : type=image,name=ghcr.io/${{ github.repository }},push-by-digest=true,name-canonical=true,push=true
265+ cache-from : type=gha,scope=docker-${{ matrix.arch }}
266+ cache-to : type=gha,scope=docker-${{ matrix.arch }},mode=max
267+
268+ - name : Export digest
269+ env :
270+ DIGEST : ${{ steps.build.outputs.digest }}
271+ run : |
272+ mkdir -p /tmp/digests
273+ touch "/tmp/digests/${DIGEST#sha256:}"
274+
275+ - name : Upload digest
276+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
277+ with :
278+ name : docker-digest-${{ matrix.arch }}
279+ path : /tmp/digests/*
280+ if-no-files-found : error
281+ retention-days : 1
282+
283+ docker-build :
284+ runs-on : ubuntu-24.04
285+ name : Docker Build & Push
286+ needs : docker-build-arch
287+ if : startsWith(github.ref, 'refs/tags/')
288+ permissions :
289+ contents : read
290+ packages : write
291+
292+ steps :
293+ - name : Download digests
294+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
295+ with :
296+ path : /tmp/digests
297+ pattern : docker-digest-*
298+ merge-multiple : true
299+
300+ - name : Log in to GitHub Container Registry
301+ uses : docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
302+ with :
303+ registry : ghcr.io
304+ username : ${{ github.actor }}
305+ password : ${{ secrets.GITHUB_TOKEN }}
306+
307+ - name : Set up Docker Buildx
308+ uses : docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
309+
310+ - name : Extract Docker metadata
311+ id : meta
312+ uses : docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
313+ with :
314+ images : ghcr.io/${{ github.repository }}
315+ tags : |
316+ type=semver,pattern={{version}}
317+ type=semver,pattern={{major}}.{{minor}}
318+ type=semver,pattern={{major}}
319+ type=raw,value=latest,enable=${{ !contains(github.ref, '-') }}
320+ type=sha,prefix=sha-
321+
322+ - name : Create multi-arch manifest list and push
323+ working-directory : /tmp/digests
324+ env :
325+ IMAGE : ghcr.io/${{ github.repository }}
326+ TAGS : ${{ steps.meta.outputs.tags }}
327+ run : |
328+ tag_args=()
329+ while IFS= read -r tag; do
330+ [[ -n "$tag" ]] && tag_args+=(-t "$tag")
331+ done <<< "$TAGS"
332+ sources=()
333+ for digest in *; do
334+ sources+=("${IMAGE}@sha256:${digest}")
335+ done
336+ docker buildx imagetools create "${tag_args[@]}" "${sources[@]}"
337+
338+ - name : Inspect image
339+ env :
340+ IMAGE : ghcr.io/${{ github.repository }}
341+ VERSION : ${{ steps.meta.outputs.version }}
342+ run : |
343+ docker buildx imagetools inspect "${IMAGE}:${VERSION}"
0 commit comments