diff --git a/.github/actions/run-tests/Dockerfile b/.github/actions/run-tests/Dockerfile index a67d9b060..e6ff50ecd 100644 --- a/.github/actions/run-tests/Dockerfile +++ b/.github/actions/run-tests/Dockerfile @@ -1,9 +1,9 @@ ARG BASE_VARIANT=bullseye -ARG GO_VERSION=1.17.5 +ARG GO_VERSION=1.17.6 ARG XX_VERSION=1.1.0 -ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2 -ARG LIBGIT2_TAG=libgit2-1.1.1-3 +ARG LIBGIT2_IMG ?= quay.io/paulinhu/golang-with-libgit2 +ARG LIBGIT2_TAG ?= static FROM tonistiigi/xx:${XX_VERSION} AS xx FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as libgit2 diff --git a/Dockerfile b/Dockerfile index 11eda1696..3ba0819a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,55 +1,11 @@ -ARG BASE_VARIANT=bullseye +ARG BASE_VARIANT=alpine ARG GO_VERSION=1.17 ARG XX_VERSION=1.1.0 -ARG LIBGIT2_IMG=ghcr.io/fluxcd/golang-with-libgit2 -ARG LIBGIT2_TAG=libgit2-1.1.1-3 +ARG LIBGIT2_IMG +ARG LIBGIT2_TAG -FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx -FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as libgit2 - -FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} as gostable - -FROM gostable AS go-linux - -FROM go-${TARGETOS} AS build-base-bullseye - -# Copy the build utilities -COPY --from=xx / / - -# Align golang base image with bookworm. -# TODO: Replace this with a golang bookworm variant, once that is released. -RUN echo "deb http://deb.debian.org/debian bookworm main" > /etc/apt/sources.list.d/bookworm.list \ - && echo "deb-src http://deb.debian.org/debian bookworm main" /etc/apt/sources.list.d/bookworm.list \ - && xx-apt update \ - && xx-apt -t bookworm upgrade -y \ - && xx-apt -t bookworm install -y curl - -COPY --from=libgit2 /Makefile /libgit2/ - -# Install the libgit2 build dependencies -RUN make -C /libgit2 cmake - -ARG TARGETPLATFORM -RUN make -C /libgit2 dependencies - -FROM build-base-${BASE_VARIANT} as libgit2-bullseye - -ARG TARGETPLATFORM - -# First build libgit2 statically, this ensures that all its dependencies -# will be statically available as well. -ARG BUILD_SHARED_LIBS=OFF -RUN FLAGS=$(xx-clang --print-cmake-defines) make -C /libgit2 libgit2 - -# Rebuild libgit2 this time to generate the shared libraries. -ARG BUILD_SHARED_LIBS=ON -RUN FLAGS=$(xx-clang --print-cmake-defines) make -C /libgit2 libgit2 -# Logs glibc version used at built time. The final image must be compatible with it. -RUN ldd --version ldd > /libgit2/built-on-glibc-version - - -FROM libgit2-${BASE_VARIANT} as build +FROM ${LIBGIT2_IMG}:${LIBGIT2_TAG} as build # Configure workspace WORKDIR /workspace @@ -64,35 +20,42 @@ COPY go.sum go.sum # Cache modules RUN go mod download -# Copy source code -COPY main.go main.go -COPY controllers/ controllers/ -COPY pkg/ pkg/ -COPY internal/ internal/ +RUN apk add clang lld pkgconfig ca-certificates -# Build the binary ENV CGO_ENABLED=1 ARG TARGETPLATFORM -# The dependencies being statically built are: libgit2, libssh2, libssl, libcrypto and libz. -# Others (such as libc, librt, libdl and libpthread) are resolved at run-time. -# To decrease the likelihood of such dependencies being out of sync, the base build image -# should be aligned with the target (i.e. same debian variant). -RUN FLAGS=$(pkg-config --static --libs --cflags libssh2 libgit2 libssl libcrypto zlib openssl) \ +RUN xx-apk add --no-cache \ + musl-dev gcc lld binutils-gold + +# Performance related changes: +# - Use read-only bind instead of copying go source files. +# - Cache go packages. +RUN --mount=target=. \ + --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=cache,target=/go/pkg \ + export LIBRARY_PATH="/usr/local/$(xx-info triple)/lib:/usr/local/$(xx-info triple)/lib64:${LIBRARY_PATH}" && \ + export PKG_CONFIG_PATH="/usr/local/$(xx-info triple)/lib/pkgconfig:/usr/local/$(xx-info triple)/lib64/pkgconfig" && \ + export FLAGS="$(pkg-config --static --libs --cflags libssh2 openssl libgit2)" && \ + CGO_LDFLAGS="${FLAGS} -static" \ xx-go build \ - -ldflags "-s -w -extldflags \"/usr/lib/$(xx-info triple)/libssh2.a /usr/lib/$(xx-info triple)/libssl.a /usr/lib/$(xx-info triple)/libcrypto.a /usr/lib/$(xx-info triple)/libz.a -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-allow-shlib-undefined ${FLAGS} -static\"" \ + -ldflags "-s -w" \ -tags 'netgo,osusergo,static_build' \ - -o source-controller -trimpath main.go; + -o /source-controller -trimpath main.go; -# The target image must aligned with apt sources used for libgit2. -FROM debian:bookworm-slim as controller +# Ensure that the binary was cross-compiled correctly to the target platform. +RUN xx-verify --static /source-controller -ARG TARGETPLATFORM -RUN apt update && apt install -y ca-certificates -# Copy over binary from build -COPY --from=build /workspace/source-controller /usr/local/bin/ -COPY --from=libgit2-bullseye /libgit2/built-on-glibc-version / +FROM gcr.io/distroless/static + +# Link repo to the GitHub Container Registry image +LABEL org.opencontainers.image.source="https://github.com/fluxcd/source-controller" + +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt + +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=build /source-controller /usr/local/bin/ COPY ATTRIBUTIONS.md / USER 65534:65534 diff --git a/Makefile b/Makefile index d3a63670d..f9ddaf499 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ IMG ?= fluxcd/source-controller TAG ?= latest # Base image used to build the Go binary -LIBGIT2_IMG ?= ghcr.io/fluxcd/golang-with-libgit2 -LIBGIT2_TAG ?= libgit2-1.1.1-3 +LIBGIT2_IMG ?= quay.io/paulinhu/golang-with-libgit2 +LIBGIT2_TAG ?= static # Allows for defining additional Docker buildx arguments, # e.g. '--push'. @@ -19,7 +19,7 @@ CRD_OPTIONS ?= crd:crdVersions=v1 REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel) # Libgit2 version -LIBGIT2_VERSION ?= 1.1.1 +LIBGIT2_VERSION ?= 1.3.0 # Other dependency versions ENVTEST_BIN_VERSION ?= 1.19.2