Skip to content

Commit

Permalink
dockerfile based binary building
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
tonistiigi committed Apr 6, 2021
1 parent 59fd6f0 commit 6423da8
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 93 deletions.
1 change: 0 additions & 1 deletion .dockerignore
@@ -1,6 +1,5 @@
.circleci
.dockerignore
.git
.github
.gitignore
appveyor.yml
Expand Down
55 changes: 55 additions & 0 deletions Dockerfile
@@ -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 changes: 45 additions & 0 deletions docker-bake.hcl
@@ -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"]
}
14 changes: 8 additions & 6 deletions scripts/build/.variables
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -eu

TARGET=${TARGET:-"build"}

PLATFORM=${PLATFORM:-}
VERSION=${VERSION:-"unknown-version"}
GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)}
Expand All @@ -20,15 +22,15 @@ export LDFLAGS="\
${LDFLAGS:-} \
"

GOOS="${GOOS:-$(go env GOHOSTOS)}"
GOARCH="${GOARCH:-$(go env GOHOSTARCH)}"
GOOS="$(go env GOOS)"
GOARCH="$(go env GOARCH)"
if [ "${GOARCH}" = "arm" ]; then
GOARM="${GOARM:-$(go env GOHOSTARM)}"
GOARM="$(go env GOARM)"
fi

TARGET="build/docker-$GOOS-$GOARCH"
TARGET="$TARGET/docker-${GOOS}-${GOARCH}"
if [ "${GOARCH}" = "arm" ] && [ -n "${GOARM}" ]; then
TARGET="${TARGET}-v${GOARM}"
TARGET="${TARGET}-v${GOARM}"
fi

if [ "${GOOS}" = "windows" ]; then
Expand Down
64 changes: 57 additions & 7 deletions scripts/build/binary
@@ -1,14 +1,64 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
#
# 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"
export CGO_ENABLED=0
go build -o "${TARGET}" --ldflags "${LDFLAGS}" "${SOURCE}"
set -x
. ./scripts/build/.variables

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"
33 changes: 0 additions & 33 deletions scripts/build/cross

This file was deleted.

24 changes: 0 additions & 24 deletions scripts/build/dynbinary

This file was deleted.

22 changes: 0 additions & 22 deletions scripts/build/osx

This file was deleted.

0 comments on commit 6423da8

Please sign in to comment.