Skip to content

Commit

Permalink
Build improvements
Browse files Browse the repository at this point in the history
- remove `.dockerignore` file
- isolate context to speed-up `docker build`
- tag build image and intermediate container automatically
- use more cosistent lower-case variable variable names
- make `git diff` error hint fixes
  • Loading branch information
errordeveloper committed Sep 5, 2019
1 parent ff598b8 commit 1539c6a
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 94 deletions.
4 changes: 4 additions & 0 deletions .build_image_manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
100644 blob 7984bfe4b3e5bdc7e2838feb954b32e9339e05bc Dockerfile
100644 blob 068bde679a10599594b7bd3ac3520c27bf800239 go.mod
100644 blob bd834def28dee387369922821becd663308e80f2 go.sum
100755 blob 98e770c77cf3b03c65cb7b7818e5f24e980f9b11 install-build-deps.sh
9 changes: 0 additions & 9 deletions .dockerignore

This file was deleted.

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ integration/kubeconfig-*

# Generated header file
.license-header

# Build image context and Docker Image ID file
.build_image_context
*.iid
51 changes: 48 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
FROM scratch
CMD eksctl
COPY --from=weaveworks/eksctl-builder:latest /out /
# Make sure to run the following commands after changes to this file are made:
# `make update-build-image-manifest && make push-build-image`

# This digest corresponds to golang:1.12.6-alpine3.9 (when Alpine was pointing to 3.9.4)
FROM golang@sha256:39677a9dd517a8e5d514dff8e36fa46ecc3fb14618b970bfaf3100cb8fab9ba6

# Build-time dependencies
RUN apk add --no-cache \
curl \
git \
make \
bash \
gcc \
g++ \
libsass-dev \
musl-dev \
&& true

WORKDIR /src
ENV CGO_ENABLED=0
COPY install-build-deps.sh go.mod go.sum /src/

# Install all go dependencies and remove the go caches in a single step to reduce the image footprint
# (caches won't be used later on, we overwrite them by volume-mounting)
RUN ./install-build-deps.sh && \
go install github.com/goreleaser/goreleaser && \
go build github.com/kubernetes-sigs/aws-iam-authenticator/cmd/aws-iam-authenticator && \
rm -rf /root/.cache/go-build /go/pkg/mod



# Runtime dependencies. Build the root filesystem of the eksctl image at /out
RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/
RUN apk add --no-cache --initdb --root /out \
alpine-baselayout \
busybox \
ca-certificates \
coreutils \
git \
libc6-compat \
openssh \
&& true

RUN mv ./aws-iam-authenticator /out/usr/local/bin/aws-iam-authenticator

ENV KUBECTL_VERSION v1.11.5
RUN curl --silent --location "https://dl.k8s.io/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" --output /out/usr/local/bin/kubectl \
&& chmod +x /out/usr/local/bin/kubectl
48 changes: 0 additions & 48 deletions Dockerfile.deps

This file was deleted.

122 changes: 90 additions & 32 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
built_at := $(shell date +%s)
git_commit := $(shell git describe --dirty --always)
git_commit = $(shell git describe --dirty --always)

git_toplevel := $(shell git rev-parse --show-toplevel)
version_pkg := github.com/weaveworks/eksctl/pkg/version

# The dependencies version should be bumped every time the build dependencies are updated
EKSCTL_DEPENDENCIES_IMAGE ?= weaveworks/eksctl-build:deps-0.15
EKSCTL_BUILDER_IMAGE ?= weaveworks/eksctl-builder:latest
EKSCTL_IMAGE ?= weaveworks/eksctl:latest
build_image_input := Dockerfile install-build-deps.sh go.mod go.sum

# We use git object hashes for determining the input files used for any given build image
# E.g. given `weaveworks/eksctl-build:e6e8800773d3adf8e7999a23dcdb07414c66a4da` one can
# run `git show e6e8800773d3adf8e7999a23dcdb07414c66a4da` to get contents of `.build_image_manifest`,
# and `git show <hash>` for each of the hashes in the manifest to determine contents of each of the
# files used in `$(build_image_input)` at the time.
build_image_tag = $(shell git ls-tree --full-tree @ -- .build_image_manifest | awk '{ print $$3 }')

build_image_name = weaveworks/eksctl-build:$(build_image_tag)

unique_tag = $(shell printf "%s-%s-%s" `git rev-parse @` $(build_image_tag) $(built_at))

intermidiate_container_name = eksctl-build-$(unique_tag)
intermediate_image_name = weaveworks/eksctl-intermediate:$(unique_tag)

GOBIN ?= $(shell echo `go env GOPATH`/bin)
eksctl_image_name ?= weaveworks/eksctl:latest

gopath := $(shell go env GOPATH)
gocache := $(shell go env GOCACHE)

docker_build := time docker build
# We should eventually switch to buildkit, as it has a many feature and cleaner output with timing info,
# but right now 'docker build' doesn't allow us to export build cache images, so we cannot use it yet
# docker_build := env DOCKER_BUILDKIT=1 $(docker_build)

GOBIN ?= $(gopath)/bin

ifeq ($(OS),Windows_NT)
TEST_TARGET=unit-test
else
TEST_TARGET=test
endif

generated_code_aws_sdk_mocks := $(wildcard pkg/eks/mocks/*API.go)

Expand Down Expand Up @@ -102,7 +130,7 @@ integration-test-container-pre-built: ## Run the integration tests inside a Dock
--volume=$(HOME)/.aws:/root/.aws \
--volume=$(HOME)/.ssh:/root/.ssh \
--workdir=/usr/local/share/eksctl \
$(EKSCTL_IMAGE) \
$(eksctl_image_name) \
eksctl-integration-test \
-eksctl.path=/usr/local/bin/eksctl \
-eksctl.kubeconfig=/tmp/kubeconfig \
Expand Down Expand Up @@ -136,7 +164,7 @@ generate-all: $(all_generated_files) # generate-ami ## Re-generate all the autom

.PHONY: check-all-generated-files-up-to-date
check-all-generated-files-up-to-date: generate-all
git diff --quiet -- $(all_generated_files) || (git --no-pager diff $(all_generated_files); exit 1)
git diff --quiet -- $(all_generated_files) || (git --no-pager diff $(all_generated_files); echo "HINT: to fix this, run 'git commit $(all_generated_files) --message \"Update generated files\"'"; exit 1)

pkg/addons/default/assets.go: pkg/addons/default/assets/*
env GOBIN=$(GOBIN) time go generate ./$(@D)
Expand All @@ -158,7 +186,7 @@ pkg/nodebootstrap/maxpods.go:
deep_copy_helper_input := $(shell $(call godeps_cmd,./pkg/apis/...) | sed 's|$(generated_code_deep_copy_helper)||' )
$(generated_code_deep_copy_helper): $(deep_copy_helper_input) .license-header ## Generate Kubernetes API helpers
time go mod download k8s.io/code-generator # make sure the code-generator is present
time env GOPATH="$$(go env GOPATH)" bash "$$(go env GOPATH)/pkg/mod/k8s.io/[email protected]/generate-groups.sh" \
time env GOPATH="$(gopath)" bash "$(gopath)/pkg/mod/k8s.io/[email protected]/generate-groups.sh" \
deepcopy,defaulter _ ./pkg/apis eksctl.io:v1alpha5 --go-header-file .license-header --output-base="$(git_toplevel)" \
|| (cat codegenheader.txt ; cat $(generated_code_deep_copy_helper); exit 1)

Expand All @@ -174,34 +202,64 @@ site/content/usage/20-schema.md: $(call godeps,cmd/schema/generate.go)
$(generated_code_aws_sdk_mocks): $(call godeps,pkg/eks/mocks/mocks.go)
mkdir -p vendor/github.com/aws/
@# Hack for Mockery to find the dependencies handled by `go mod`
ln -sfn "$$(go env GOPATH)/pkg/mod/github.com/aws/[email protected]" vendor/github.com/aws/aws-sdk-go
ln -sfn "$(gopath)/pkg/mod/github.com/aws/[email protected]" vendor/github.com/aws/aws-sdk-go
time env GOBIN=$(GOBIN) go generate ./pkg/eks/mocks

##@ Docker

ifeq ($(OS),Windows_NT)
TEST_TARGET=unit-test
else
TEST_TARGET=test
endif

.PHONY: eksctl-deps-image
eksctl-deps-image: ## Create a cache image with dependencies
-time docker pull $(EKSCTL_DEPENDENCIES_IMAGE)
@# Pin dependency file permissions.
@# Docker uses the file permissions as part of the COPY hash, which can lead to cache misses
@# in hosts with different default file permissions (umask).
chmod 0700 install-build-deps.sh
chmod 0600 go.mod go.sum
time docker build --cache-from=$(EKSCTL_DEPENDENCIES_IMAGE) --tag=$(EKSCTL_DEPENDENCIES_IMAGE) -f Dockerfile.deps .
update_build_image_manifest = git ls-tree --full-tree @ -- $(build_image_input) > .build_image_manifest

.PHONY: check-build-image-manifest-up-to-date
check-build-image-manifest-up-to-date: ## Update build image manifest and commits the changes
git diff --quiet -- $(build_image_input) || (git --no-pager diff $(build_image_input); exit 1)
$(update_build_image_manifest)
git diff --quiet -- .build_image_manifest || (git --no-pager diff .build_image_manifest; echo "HINT: to fix this, run 'make update-build-image-manifest'"; exit 1)

.PHONY: update-build-image-manifest
update-build-image-manifest: ## Update build image manifest and commits the changes
$(update_build_image_manifest)
git commit --quiet .build_image_manifest --message 'Update build image manifest'
$(info build image name is $(build_image_name))

.PHONY: build-image
build-image: check-build-image-manifest-up-to-date ## Build the build image that has all of external dependencies
-docker pull $(build_image_name)
rm -rf .build_image_context
mkdir .build_image_context
cp $(build_image_input) .build_image_context/
# git only ensures owner's perssions are set, it ignores group and other's permissions,
# we need to force permissions here to avoid cache misses
chmod go-wrx .build_image_context/*
$(docker_build) \
--iidfile=.build_image.iid \
--cache-from=$(build_image_name) \
--tag=$(build_image_name) \
.build_image_context/

.PHONY: push-build-image
push-build-image: build-image ## Push the build image to the registry
docker push $(file < .build_image.iid)

.PHONY: intermediate-image
intermediate-image: build-image ## Build the intermediate image that has all artefacts
time docker run \
--tty \
--name=$(intermidiate_container_name) \
--env=TEST_TARGET=$(TEST_TARGET) \
--volume=$(git_toplevel):/src \
--volume=$(gocache):/root/.cache/go-build \
--volume=$(gopath)/pkg/mod:/go/pkg/mod \
$(file < .build_image.iid) /src/eksctl-image-builder.sh \
|| (docker rm $(intermidiate_container_name) ; exit 1)
time docker commit $(intermidiate_container_name) $(intermediate_image_name) \
&& docker rm $(intermidiate_container_name)

.PHONY: eksctl-image
eksctl-image: eksctl-deps-image## Create the eksctl image
time docker run -t --name eksctl-builder -e TEST_TARGET=$(TEST_TARGET) \
-v "$(git_toplevel)":/src -v "$$(go env GOCACHE):/root/.cache/go-build" -v "$$(go env GOPATH)/pkg/mod:/go/pkg/mod" \
$(EKSCTL_DEPENDENCIES_IMAGE) /src/eksctl-image-builder.sh || ( docker rm eksctl-builder; exit 1 )
time docker commit eksctl-builder $(EKSCTL_BUILDER_IMAGE) && docker rm eksctl-builder
docker build --tag $(EKSCTL_IMAGE) .
eksctl-image: intermediate-image ## Build the eksctl image that has release artefacts and no build dependencies
printf 'FROM scratch\nCMD eksctl\nCOPY --from=%s /out /' $(intermediate_image_name) \
| $(docker_build) \
--iidfile=.eksctl_image.iid \
--tag="$(eksctl_image_name)" -

##@ Release

Expand All @@ -211,7 +269,7 @@ docker_run_release_script = docker run \
--env=CIRCLE_PROJECT_USERNAME \
--volume=$(CURDIR):/src \
--workdir=/src \
$(EKSCTL_BUILDER_IMAGE)
$(intermediate_image_name)

.PHONY: release-candidate
release-candidate: eksctl-image ## Create a new eksctl release candidate
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Make sure to bump the version of EKSCTL_DEPENDENCIES_IMAGE if you make any changes here
// Make sure to run the following commands after changes to this file are made:
// `make update-build-image-manifest && make push-build-image`
module github.com/weaveworks/eksctl

go 1.12
Expand Down
3 changes: 2 additions & 1 deletion install-build-deps.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh -eux

# Make sure to bump the version of EKSCTL_DEPENDENCIES_IMAGE if you make any changes here
# Make sure to run the following commands after changes to this file are made:
# `make update-build-image-manifest && make push-build-image`

if [ -z "${GOBIN+x}" ]; then
GOBIN="$(go env GOPATH)/bin"
Expand Down

0 comments on commit 1539c6a

Please sign in to comment.