From a3a00016fb7dc0f107a2feb6daf51b3acb53f8ae Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Sun, 29 Sep 2024 19:30:04 +0200 Subject: [PATCH] ci: Build multi-platform image with cross-compilation The previous build workflow used emulation to build the Docker image, which results in a somewhat complicated push-by-digest and merge workflow to create a multi-platform image. This commit changes the Docker build to use cross-compilation instead, resulting in a faster and more straightforward build. Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> --- .github/workflows/image.yml | 83 ++++--------------------------------- Dockerfile | 30 ++++++++++---- 2 files changed, 29 insertions(+), 84 deletions(-) diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml index be128d6fd..95a4ad0b6 100644 --- a/.github/workflows/image.yml +++ b/.github/workflows/image.yml @@ -3,6 +3,7 @@ name: Build Docker image on: release: types: [published] + pull_request: permissions: packages: write @@ -12,18 +13,8 @@ env: jobs: build: runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64 - steps: - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + steps: - name: Checkout uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 @@ -33,9 +24,6 @@ jobs: with: images: ${{ env.REGISTRY_IMAGE }} - - name: Set up QEMU - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 @@ -47,69 +35,14 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push by digest + - name: Build and push id: build uses: docker/build-push-action@16ebe778df0e7752d2cfcbd924afdbbd89c1a755 # v6.6.1 with: context: . - push: ${{ startsWith(github.ref, 'refs/tags') }} - platforms: ${{ matrix.platform }} + provenance: mode=max + sbom: true + push: ${{ github.event_name != 'pull_request' }} + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - build - steps: - - name: Download digests - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - path: /tmp/digests - pattern: digests-* - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 - - - name: Docker meta - id: meta - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 - with: - images: ${{ env.REGISTRY_IMAGE }} - - flavor: | - latest=false - - - name: Login to GHCR - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Create manifest list and push - if: ${{ startsWith(github.ref, 'refs/tags') }} - working-directory: /tmp/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 - if: ${{ startsWith(github.ref, 'refs/tags') }} - run: | - docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} diff --git a/Dockerfile b/Dockerfile index fb72b77f1..afe5cf132 100755 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,17 @@ # Twitter: https://twitter.com/gohugoio # Website: https://gohugo.io/ -FROM golang:1.22.6-alpine AS build +FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx + +FROM --platform=$BUILDPLATFORM golang:1.22.6-alpine AS build + +# Set up cross-compilation helpers +COPY --from=xx / / +RUN apk add clang lld # Optionally set HUGO_BUILD_TAGS to "extended" or "nodeploy" when building like so: # docker build --build-arg HUGO_BUILD_TAGS=extended . -ARG HUGO_BUILD_TAGS +ARG HUGO_BUILD_TAGS="none" ARG CGO=1 ENV CGO_ENABLED=${CGO} @@ -15,20 +21,26 @@ ENV GO111MODULE=on WORKDIR /go/src/github.com/gohugoio/hugo -COPY . /go/src/github.com/gohugoio/hugo/ +RUN --mount=src=go.mod,target=go.mod \ + --mount=src=go.sum,target=go.sum \ + --mount=type=cache,target=/go/pkg/mod \ + go mod download +ARG TARGETPLATFORM # gcc/g++ are required to build SASS libraries for extended version -RUN apk update && \ - apk add --no-cache gcc g++ musl-dev git && \ - go install github.com/magefile/mage - -RUN mage hugo && mage install +RUN xx-apk add --no-scripts --no-cache gcc g++ musl-dev git +RUN --mount=target=. \ + --mount=type=cache,target=/go/pkg/mod <