dockerfile based binary building

Using cross compilation toolchains that work from any platform
Adds darwin/arm64 support and bake targets. Static and dynamic
binary targets are available, both with glibc and musl.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi 2021-03-02 23:03:02 -08:00
parent 59fd6f0270
commit 6423da8dcd
8 changed files with 165 additions and 93 deletions

View File

@ -1,6 +1,5 @@
.circleci .circleci
.dockerignore .dockerignore
.git
.github .github
.gitignore .gitignore
appveyor.yml appveyor.yml

55
Dockerfile Normal file
View File

@ -0,0 +1,55 @@
#syntax=docker/dockerfile:1.2
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.13.15
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} AS gostable
FROM --platform=$BUILDPLATFORM golang:1.16-${BASE_VARIANT} AS golatest
FROM gostable AS go-linux
FROM gostable AS go-windows
FROM golatest AS go-darwin
FROM --platform=$BUILDPLATFORM tonistiigi/xx@sha256:810dc54d5144f133a218e88e319184bf8b9ce01d37d46ddb37573e90decd9eef AS xx
FROM go-${TARGETOS} AS build-base-alpine
COPY --from=xx / /
RUN apk add --no-cache clang lld file
WORKDIR /go/src/github.com/docker/cli
FROM build-base-alpine AS build-alpine
ARG TARGETPLATFORM
# gcc is installed for libgcc only
RUN xx-apk add --no-cache musl-dev gcc
FROM go-${TARGETOS} AS build-base-buster
COPY --from=xx / /
RUN apt-get update && apt-get install --no-install-recommends -y clang lld file
WORKDIR /go/src/github.com/docker/cli
FROM build-base-buster AS build-buster
ARG TARGETPLATFORM
RUN xx-apt install --no-install-recommends -y libc6-dev libgcc-8-dev
FROM build-${BASE_VARIANT} AS build
# GO_LINKMODE defines if static or dynamic binary should be produced
ARG GO_LINKMODE=static
# GO_BUILDTAGS defines additional build tags
ARG GO_BUILDTAGS
# GO_STRIP strips debugging symbols if set
ARG GO_STRIP
# CGO_ENABLED manually sets if cgo is used
ARG CGO_ENABLED
# VERSION sets the version for the produced binary
ARG VERSION
RUN --mount=ro --mount=type=cache,target=/root/.cache \
--mount=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
xx-go --wrap && \
# export GOCACHE=$(go env GOCACHE)/$(xx-info)$([ -f /etc/alpine-release ] && echo "alpine") && \
TARGET=/out ./scripts/build/binary && \
xx-verify $([ "$GO_LINKMODE" = "static" ] && echo "--static") /out/docker
FROM build-base-${BASE_VARIANT} AS dev
FROM scratch AS binary
COPY --from=build /out .

45
docker-bake.hcl Normal file
View File

@ -0,0 +1,45 @@
variable "VERSION" {
default = ""
}
variable "USE_GLIBC" {
default = ""
}
variable "STRIP_TARGET" {
default = ""
}
group "default" {
targets = ["binary"]
}
target "binary" {
target = "binary"
platforms = ["local"]
output = ["build"]
args = {
BASE_VARIANT = USE_GLIBC != "" ? "buster" : "alpine"
VERSION = VERSION
GO_STRIP = STRIP_TARGET
}
}
target "dynbinary" {
inherits = ["binary"]
args = {
GO_LINKMODE = "dynamic"
}
}
target "_all_platforms" {
platforms = ["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64", "windows/arm", "windows/386"]
}
target "cross" {
inherits = ["binary", "_all_platforms"]
}
target "dynbinary-cross" {
inherits = ["dynbinary", "_all_platforms"]
}

View File

@ -1,6 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env sh
set -eu set -eu
TARGET=${TARGET:-"build"}
PLATFORM=${PLATFORM:-} PLATFORM=${PLATFORM:-}
VERSION=${VERSION:-"unknown-version"} VERSION=${VERSION:-"unknown-version"}
GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)} GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)}
@ -20,15 +22,15 @@ export LDFLAGS="\
${LDFLAGS:-} \ ${LDFLAGS:-} \
" "
GOOS="${GOOS:-$(go env GOHOSTOS)}" GOOS="$(go env GOOS)"
GOARCH="${GOARCH:-$(go env GOHOSTARCH)}" GOARCH="$(go env GOARCH)"
if [ "${GOARCH}" = "arm" ]; then if [ "${GOARCH}" = "arm" ]; then
GOARM="${GOARM:-$(go env GOHOSTARM)}" GOARM="$(go env GOARM)"
fi fi
TARGET="build/docker-$GOOS-$GOARCH" TARGET="$TARGET/docker-${GOOS}-${GOARCH}"
if [ "${GOARCH}" = "arm" ] && [ -n "${GOARM}" ]; then if [ "${GOARCH}" = "arm" ] && [ -n "${GOARM}" ]; then
TARGET="${TARGET}-v${GOARM}" TARGET="${TARGET}-v${GOARM}"
fi fi
if [ "${GOOS}" = "windows" ]; then if [ "${GOOS}" = "windows" ]; then

View File

@ -1,14 +1,64 @@
#!/usr/bin/env bash #!/usr/bin/env sh
# #
# Build a static binary for the host OS/ARCH # Build a static binary for the host OS/ARCH
# #
set -eu -o pipefail set -eu
source ./scripts/build/.variables : "${CGO_ENABLED=}"
: "${GO_LINKMODE=static}"
: "${GO_BUILDMODE=}"
: "${GO_BUILDTAGS=}"
: "${GO_STRIP=}"
echo "Building statically linked $TARGET" set -x
export CGO_ENABLED=0 . ./scripts/build/.variables
go build -o "${TARGET}" --ldflags "${LDFLAGS}" "${SOURCE}"
ln -sf "$(basename "${TARGET}")" build/docker if [ -z "$CGO_ENABLED" ]; then
case "$(go env GOOS)" in
linux)
case "$(go env GOARCH)" in
amd64|arm64|arm|s390x)
CGO_ENABLED=1
;;
*)
CGO_ENABLED=0
;;
esac
;;
darwin|windows)
CGO_ENABLED=1
;;
*)
CGO_ENABLED=0
;;
esac
fi
export CGO_ENABLED
if [ "$CGO_ENABLED" = "1" ] && [ "$(go env GOOS)" != "windows" ]; then
case "$(go env GOARCH)" in
mips*|ppc64)
# pie build mode is not supported on mips architectures
;;
*)
GO_BUILDMODE="-buildmode=pie"
;;
esac
GO_BUILDTAGS="$GO_BUILDTAGS pkcs11"
fi
if [ "$CGO_ENABLED" = "1" ] && [ "$GO_LINKMODE" = "static" ] && [ "$(go env GOOS)" = "linux" ]; then
LDFLAGS="$LDFLAGS -extldflags -static"
fi
if [ -n "$GO_STRIP" ]; then
LDFLAGS="$LDFLAGS -s -w"
fi
echo "Building $GO_LINKMODE $(basename "${TARGET}")"
export GO111MODULE=auto
go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}"
ln -sf "$(basename "${TARGET}")" "$(dirname "${TARGET}")/docker"

View File

@ -1,33 +0,0 @@
#!/usr/bin/env bash
#
# Build a binary for all supported platforms
#
set -eu -o pipefail
BUILDDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export SHELL=bash
jobs=(
"$BUILDDIR/windows" \
"$BUILDDIR/osx" \
"GOOS=linux GOARCH=amd64 $BUILDDIR/binary" \
"GOOS=linux GOARCH=arm $BUILDDIR/binary" \
"GOOS=linux GOARCH=ppc64le $BUILDDIR/binary" \
"GOOS=linux GOARCH=s390x $BUILDDIR/binary" \
)
# Outside of circleCI run all at once. On circleCI run two at a time because
# each container has access to two cores.
group=${CROSS_GROUP-"all"}
if [ "$group" = "all" ]; then
echo "Building binaries for all platforms"
parallel ::: "${jobs[@]}"
exit 0
fi
declare -i start="$group*2"
parallel ::: "${jobs[@]:$start:2}"

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
#
# Build a dynamically linked binary for the host OS/ARCH
#
set -eu -o pipefail
source ./scripts/build/.variables
echo "Building dynamically linked $TARGET"
export CGO_ENABLED=1
case "$(go env GOARCH)" in
mips*|ppc64)
# pie build mode is not supported on mips architectures
GO_BUILDMODE=""
;;
*)
GO_BUILDMODE="-buildmode=pie"
;;
esac
go build -o "${TARGET}" -tags pkcs11 --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}"
ln -sf "$(basename "${TARGET}")" build/docker

View File

@ -1,22 +0,0 @@
#!/usr/bin/env bash
#
# Build an osx binary from linux
#
set -eu -o pipefail
source ./scripts/build/.variables
export CGO_ENABLED=1
export GOOS=darwin
export GOARCH=amd64
export CC=o64-clang
export CXX=o64-clang++
export LDFLAGS="$LDFLAGS -linkmode external -s"
export LDFLAGS_STATIC_DOCKER='-extld='${CC}
# Override TARGET
TARGET="build/docker-$GOOS-$GOARCH"
echo "Building $TARGET"
go build -o "${TARGET}" -tags pkcs11 --ldflags "${LDFLAGS}" "${SOURCE}"