Compare commits

...

2 Commits

Author SHA1 Message Date
Bjørn Erik Pedersen 4c3347a77f 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
2024-10-11 15:01:08 +02:00
David Karlsson a3a00016fb 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>
2024-10-09 11:25:45 +02:00
5 changed files with 125 additions and 101 deletions
+2 -2
View File
@@ -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
+8 -75
View File
@@ -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 }}
+74 -24
View File
@@ -2,44 +2,94 @@
# Twitter: https://twitter.com/gohugoio
# Website: https://gohugo.io/
FROM golang:1.22.6-alpine AS build
ARG GO_VERSION="1.23.2"
ARG ALPINE_VERSION=3.20
# 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
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
ARG CGO=1
ENV CGO_ENABLED=${CGO}
ENV GOOS=linux
ENV GO111MODULE=on
FROM gobuild AS build
RUN apk add clang lld
# Set up cross-compilation helpers
COPY --from=xx / /
ARG TARGETPLATFORM
RUN xx-apk add musl-dev gcc g++
# 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
COPY . /go/src/github.com/gohugoio/hugo/
# 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 \
--mount=type=cache,target=/root/.cache/go-build,id=go-build-$TARGETPLATFORM <<EOT
set -ex
xx-go build -tags "$HUGO_BUILD_TAGS" -ldflags "-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=docker" -o /usr/bin/hugo
xx-verify /usr/bin/hugo
EOT
# 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
FROM gorun AS final
RUN mage hugo && mage install
COPY --from=build /usr/bin/hugo /usr/bin/hugo
# ---
# libc6-compat are required for extended libraries (libsass, libwebp).
RUN apk add --no-cache \
libc6-compat \
git \
runuser \
curl \
nodejs \
npm
FROM alpine:3.18
RUN mkdir -p /var/hugo/bin && \
addgroup -Sg 1000 hugo && \
adduser -Sg hugo -u 1000 -h /var/hugo hugo && \
chown -R hugo: /var/hugo && \
# For the Hugo's Git integration to work.
runuser -u hugo -- git config --global --add safe.directory /project && \
# See https://github.com/gohugoio/hugo/issues/9810
runuser -u hugo -- git config --global core.quotepath false
COPY --from=build /go/bin/hugo /usr/bin/hugo
VOLUME /project
WORKDIR /project
USER hugo:hugo
ENV HUGO_CACHEDIR=/cache
ARG BUILDARCH
ENV BUILDARCH=${BUILDARCH}
ENV PATH="/var/hugo/bin:$PATH"
# libc6-compat & libstdc++ are required for extended SASS libraries
# ca-certificates are required to fetch outside resources (like Twitter oEmbeds)
RUN apk update && \
apk add --no-cache ca-certificates libc6-compat libstdc++ git
COPY scripts/docker scripts/docker
COPY scripts/docker/entrypoint.sh /entrypoint.sh
VOLUME /site
WORKDIR /site
# Install default dependencies.
RUN scripts/docker/install_runtimedeps_default.sh
# Update PATH to reflect the new dependencies.
# For more complex setups, we should probably find a way to
# delegate this to the script itself, but this will have to do for now.
# Also, the dart-sass binary is a little special, other binaries can be put/linked
# directly in /var/hugo/bin.
ENV PATH="/var/hugo/bin/dart-sass:$PATH"
# Expose port for live server
EXPOSE 1313
ENTRYPOINT ["hugo"]
ENTRYPOINT ["/entrypoint.sh"]
CMD ["--help"]
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
# Check if a custom hugo-docker-entrypoint.sh file exists.
if [ -f hugo-docker-entrypoint.sh ]; then
# Execute the custom entrypoint file.
sh hugo-docker-entrypoint.sh "$@"
exit $?
fi
# Check if a package.json file exists.
if [ -f package.json ]; then
# Check if node_modules exists.
if [ ! -d node_modules ]; then
# Install npm packages.
# Note that we deliberately do not use `npm ci` here, as it would fail if the package-lock.json file is not up-to-date,
# which would be the case if you run the container with a different OS or architecture than the one used to create the package-lock.json file.
npm i
fi
fi
exec "hugo" "$@"
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
set -ex
export DART_SASS_VERSION=1.79.3
# If $BUILDARCH=arm64, then we need to install the arm64 version of Dart Sass,
# otherwise we install the x64 version.
ARCH="x64"
if [ "$BUILDARCH" = "arm64" ]; then
ARCH="arm64"
fi
cd /tmp
curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-${ARCH}.tar.gz
ls -ltr
tar -xf dart-sass-${DART_SASS_VERSION}-linux-${ARCH}.tar.gz
rm dart-sass-${DART_SASS_VERSION}-linux-${ARCH}.tar.gz && \
# The dart-sass folder is added to the PATH by the caller.
mv dart-sass /var/hugo/bin