Skip to content

Commit

Permalink
Merge pull request #2993 from tonistiigi/xx-build
Browse files Browse the repository at this point in the history
dockerfile based binary building
  • Loading branch information
thaJeztah authored Apr 7, 2021
2 parents 59fd6f0 + 26b633d commit a32cd16
Show file tree
Hide file tree
Showing 16 changed files with 238 additions and 225 deletions.
24 changes: 9 additions & 15 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
docker: [{image: 'docker:19.03-git'}]
environment:
DOCKER_BUILDKIT: 1
BUILDX_VERSION: "v0.5.1"
parallelism: 3
steps:
- checkout
Expand All @@ -55,21 +56,14 @@ jobs:
- run:
name: "Docker info"
command: docker info
- run:
name: "Cross - build image"
command: |
docker build --progress=plain -f dockerfiles/Dockerfile.cross --tag cli-builder:$CIRCLE_BUILD_NUM .
- run:
name: "Cross"
command: |
name=cross-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX
docker run \
-e CROSS_GROUP=$CIRCLE_NODE_INDEX \
--name $name cli-builder:$CIRCLE_BUILD_NUM \
make cross
docker cp \
$name:/go/src/github.com/docker/cli/build \
/work/build
- run: apk add make curl
- run: mkdir -vp ~/.docker/cli-plugins/
- run: curl -fsSL --output ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/${BUILDX_VERSION}/buildx-${BUILDX_VERSION}.linux-amd64
- run: chmod a+x ~/.docker/cli-plugins/docker-buildx
- run: docker buildx version
- run: docker context create buildctx
- run: docker buildx create --use buildctx && docker buildx inspect --bootstrap
- run: GROUP_INDEX=$CIRCLE_NODE_INDEX GROUP_TOTAL=$CIRCLE_NODE_TOTAL docker buildx bake cross --progress=plain
- store_artifacts:
path: /work/build

Expand Down
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.circleci
.dockerignore
.git
.github
.gitignore
appveyor.yml
Expand Down
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
Thumbs.db
.editorconfig
/build/
cli/winresources/rsrc_386.syso
cli/winresources/rsrc_amd64.syso
cli/winresources/rsrc_*.syso
/man/man1/
/man/man5/
/man/man8/
Expand Down
61 changes: 61 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#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 golatest AS go-darwin
FROM golatest AS go-windows-amd64
FROM golatest AS go-windows-386
FROM golatest AS go-windows-arm
FROM --platform=$BUILDPLATFORM tonistiigi/golang:497feff1-${BASE_VARIANT} AS go-windows-arm64
FROM go-windows-${TARGETARCH} AS go-windows

FROM --platform=$BUILDPLATFORM tonistiigi/xx@sha256:620d36a9d7f1e3b102a5c7e8eff12081ac363828b3a44390f24fa8da2d49383d AS xx

FROM go-${TARGETOS} AS build-base-alpine
COPY --from=xx / /
RUN apk add --no-cache clang lld llvm file git
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 \
--mount=type=tmpfs,target=cli/winresources \
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
COPY . .

FROM scratch AS binary
COPY --from=build /out .
19 changes: 5 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,28 @@ lint: ## run all the lint tools
gometalinter --config gometalinter.json ./...

.PHONY: binary
binary: ## build executable for Linux
@echo "WARNING: binary creates a Linux executable. Use cross for macOS or Windows."
./scripts/build/binary
binary:
docker buildx bake binary

.PHONY: plugins
plugins: ## build example CLI plugins
./scripts/build/plugins

.PHONY: cross
cross: ## build executable for macOS and Windows
./scripts/build/cross

.PHONY: binary-windows
binary-windows: ## build executable for Windows
./scripts/build/windows
cross:
docker buildx bake cross

.PHONY: plugins-windows
plugins-windows: ## build example CLI plugins for Windows
./scripts/build/plugins-windows

.PHONY: binary-osx
binary-osx: ## build executable for macOS
./scripts/build/osx

.PHONY: plugins-osx
plugins-osx: ## build example CLI plugins for macOS
./scripts/build/plugins-osx

.PHONY: dynbinary
dynbinary: ## build dynamically linked binary
./scripts/build/dynbinary
USE_GLIBC=1 docker buildx bake dynbinary

vendor: vendor.conf ## check that vendor matches vendor.conf
rm -rf vendor
Expand Down
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,31 @@ Development

`docker/cli` is developed using Docker.

Build a linux binary:
Build CLI from source:

```
$ make -f docker.Makefile binary
$ docker buildx bake
```

Build binaries for all supported platforms:

```
$ make -f docker.Makefile cross
$ docker buildx bake cross
```

Build for a specific platform:

```
$ docker buildx bake --set binary.platform=linux/arm64
```

Build dynamic binary for glibc or musl:

```
$ USE_GLIBC=1 docker buildx bake dynbinary
```


Run all linting:

```
Expand All @@ -44,12 +57,6 @@ Start an interactive development environment:
$ make -f docker.Makefile shell
```

In the development environment you can run many tasks, including build binaries:

```
$ make binary
```

Legal
=====
*Brought to you courtesy of our legal counsel. For more context,
Expand Down
4 changes: 1 addition & 3 deletions cli/winresources/res_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ These resources are used to provide
* An icon
* A Windows manifest declaring Windows version support
The resource object files are generated with go generate.
The resource object files are generated when building with scripts/build/binary .
The resource source files are located in scripts/winresources.
This occurs automatically when you run scripts/build/windows.
Expand All @@ -14,5 +14,3 @@ is included.
*/
package winresources

//go:generate ../../scripts/gen/windows-resources
63 changes: 63 additions & 0 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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"
}
}

variable "GROUP_TOTAL" {
default = "1"
}

variable "GROUP_INDEX" {
default = "0"
}

function "platforms" {
params = [USE_GLIBC]
result = concat(["linux/amd64", "linux/386", "linux/arm64", "linux/arm", "linux/ppc64le", "linux/s390x", "darwin/amd64", "darwin/arm64", "windows/amd64", "windows/arm", "windows/386"], USE_GLIBC!=""?[]:["windows/arm64"])
}

function "glen" {
params = [platforms, GROUP_TOTAL]
result = ceil(length(platforms)/GROUP_TOTAL)
}

target "_all_platforms" {
platforms = slice(platforms(USE_GLIBC), GROUP_INDEX*glen(platforms(USE_GLIBC), GROUP_TOTAL),min(length(platforms(USE_GLIBC)), (GROUP_INDEX+1)*glen(platforms(USE_GLIBC), GROUP_TOTAL)))
}

target "cross" {
inherits = ["binary", "_all_platforms"]
}

target "dynbinary-cross" {
inherits = ["dynbinary", "_all_platforms"]
}
20 changes: 0 additions & 20 deletions docker.Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ build_linter_image:
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
cat ./dockerfiles/Dockerfile.lint | docker build ${DOCKER_BUILD_ARGS} --build-arg=GO_VERSION -t $(LINTER_IMAGE_NAME) -

.PHONY: build_cross_image
build_cross_image:
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
cat ./dockerfiles/Dockerfile.cross | docker build ${DOCKER_BUILD_ARGS} --build-arg=GO_VERSION -t $(CROSS_IMAGE_NAME) -

.PHONY: build_shell_validate_image
build_shell_validate_image:
# build dockerfile from stdin so that we don't send the build-context; source is bind-mounted in the development environment
Expand Down Expand Up @@ -80,22 +75,10 @@ test-unit: build_docker_image ## run unit tests (using go test)
.PHONY: test ## run unit and e2e tests
test: test-unit test-e2e

.PHONY: cross
cross: build_cross_image ## build the CLI for macOS and Windows
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make cross

.PHONY: binary-windows
binary-windows: build_cross_image ## build the CLI for Windows
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@

.PHONY: plugins-windows
plugins-windows: build_cross_image ## build the example CLI plugins for Windows
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@

.PHONY: binary-osx
binary-osx: build_cross_image ## build the CLI for macOS
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@

.PHONY: plugins-osx
plugins-osx: build_cross_image ## build the example CLI plugins for macOS
$(DOCKER_RUN) $(CROSS_IMAGE_NAME) make $@
Expand All @@ -120,9 +103,6 @@ fmt: ## run gofmt
vendor: build_docker_image vendor.conf ## download dependencies (vendor/) listed in vendor.conf
$(DOCKER_RUN) -it $(DEV_DOCKER_IMAGE_NAME) make vendor

dynbinary: build_cross_image ## build the CLI dynamically linked
$(DOCKER_RUN) -it $(CROSS_IMAGE_NAME) make dynbinary

.PHONY: authors
authors: ## generate AUTHORS file from git history
$(DOCKER_RUN) -it $(DEV_DOCKER_IMAGE_NAME) make authors
Expand Down
16 changes: 9 additions & 7 deletions scripts/build/.variables
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
set -eu

TARGET=${TARGET:-"build"}

PLATFORM=${PLATFORM:-}
VERSION=${VERSION:-"unknown-version"}
VERSION=${VERSION:-$(git describe --match 'v[0-9]*' --dirty='.m' --always --tags | sed 's/^v//' 2>/dev/null || echo "unknown-version" )}
GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)}
BUILDTIME=${BUILDTIME:-$(date -u +"%Y-%m-%dT%H:%M:%SZ")}

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
Loading

0 comments on commit a32cd16

Please sign in to comment.