Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc Docker + Go version upgrade #12921

Merged
merged 2 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
83 changes: 8 additions & 75 deletions .github/workflows/image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Build Docker image
on:
release:
types: [published]
pull_request:
permissions:
packages: write

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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 }}
98 changes: 74 additions & 24 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 21 additions & 0 deletions scripts/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions scripts/docker/install_runtimedeps_default.sh
Original file line number Diff line number Diff line change
@@ -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