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 1/2] 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 be128d6fd32..95a4ad0b638 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 fb72b77f18c..afe5cf1322c 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 < Date: Wed, 9 Oct 2024 11:39:36 +0200 Subject: [PATCH 2/2] Upgrade to latest Go version + Some Docker image improvements (note) * Rename /site to /project * Add ldflags * Add go and node to the default image * Add Dart Sass to the default image * Build the extended version by default * Add "npm i" install support with custom entry script override * Adjust cache logic to speed up CGO rebuilds Closes #12920 See #12885 --- .circleci/config.yml | 4 +- Dockerfile | 96 +++++++++++++------ scripts/docker/entrypoint.sh | 21 ++++ scripts/docker/install_runtimedeps_default.sh | 20 ++++ 4 files changed, 110 insertions(+), 31 deletions(-) create mode 100755 scripts/docker/entrypoint.sh create mode 100755 scripts/docker/install_runtimedeps_default.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ff9559365e..6a82e96b7d0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,7 @@ parameters: defaults: &defaults resource_class: large docker: - - image: bepsays/ci-hugoreleaser:1.22300.20000 + - image: bepsays/ci-hugoreleaser:1.22300.20200 environment: &buildenv GOMODCACHE: /root/project/gomodcache version: 2 @@ -60,7 +60,7 @@ jobs: environment: <<: [*buildenv] docker: - - image: bepsays/ci-hugoreleaser-linux-arm64:1.22300.20000 + - image: bepsays/ci-hugoreleaser-linux-arm64:1.22300.20200 steps: - *restore-cache - &attach-workspace diff --git a/Dockerfile b/Dockerfile index afe5cf1322c..394133aed9e 100755 --- a/Dockerfile +++ b/Dockerfile @@ -2,56 +2,94 @@ # Twitter: https://twitter.com/gohugoio # Website: https://gohugo.io/ +ARG GO_VERSION="1.23.2" +ARG ALPINE_VERSION=3.20 + FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS gobuild +FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS gorun + -FROM --platform=$BUILDPLATFORM golang:1.22.6-alpine AS build +FROM gobuild AS build + +RUN apk add clang lld # 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="none" +ARG TARGETPLATFORM +RUN xx-apk add musl-dev gcc g++ -ARG CGO=1 -ENV CGO_ENABLED=${CGO} -ENV GOOS=linux -ENV GO111MODULE=on +# Optionally set HUGO_BUILD_TAGS to "none" or "nodeploy" when building like so: +# docker build --build-arg HUGO_BUILD_TAGS=nodeploy . +# +# We build the extended version by default. +ARG HUGO_BUILD_TAGS="extended" +ENV CGO_ENABLED=1 +ENV GOPROXY=https://proxy.golang.org +ENV GOCACHE=/root/.cache/go-build +ENV GOMODCACHE=/go/pkg/mod +ARG TARGETPLATFORM WORKDIR /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 xx-apk add --no-scripts --no-cache gcc g++ musl-dev git +# For --mount=type=cache the value of target is the default cache id, so +# for the go mod cache it would be good if we could share it with other Go images using the same setup, +# but the go build cache needs to be per platform. +# See this comment: https://github.com/moby/buildkit/issues/1706#issuecomment-702238282 RUN --mount=target=. \ - --mount=type=cache,target=/go/pkg/mod <