diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 653c3285..27208466 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -39,7 +39,7 @@ jobs: - name: Build and push Docker image run: | - make ko-push IMG=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }},latest + make docker-buildx IMG=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }} publish-helm-charts-containers: needs: build-and-push-image diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..6220d626 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# Build the manager binary +FROM registry.access.redhat.com/ubi9/go-toolset:1.22.9 AS builder +ARG TARGETOS +ARG TARGETARCH + +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY cmd/main.go cmd/main.go +COPY api/ api/ +COPY internal/ internal/ + +# Build +# the GOARCH has not a default value to allow the binary be built according to the host where the command +# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO +# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, +# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. +RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go + +FROM registry.access.redhat.com/ubi9/ubi-micro:9.5 +WORKDIR / +COPY --from=builder /opt/app-root/src/manager . +USER 65532:65532 + +ENTRYPOINT ["/manager"] diff --git a/Makefile b/Makefile index d316a6c4..6986b6ee 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ GO_FILES := $(shell find ./ -name ".go" -not -path "./bin" -not -path "./packagi # Image URL to use all building/pushing image targets IMG ?= quay.io/jumpstarter-dev/jumpstarter-controller:latest -KO_DOCKER_REPO = $(shell echo $(IMG) | cut -d: -f1) -KO_DOCKER_TAG = $(shell echo $(IMG) | cut -d: -f2) +DOCKER_REPO = $(shell echo $(IMG) | cut -d: -f1) +DOCKER_TAG = $(shell echo $(IMG) | cut -d: -f2) # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. ENVTEST_K8S_VERSION = 1.30.0 @@ -14,6 +14,12 @@ else GOBIN=$(shell go env GOBIN) endif +# CONTAINER_TOOL defines the container tool to be used for building images. +# Be aware that the target commands are only tested with Docker which is +# scaffolded by default. However, you might want to replace it to use other +# tools. (i.e. podman) +CONTAINER_TOOL ?= docker + # Setting SHELL to bash allows bash commands to be executed by recipes. # Options are set to exit when a recipe line exits non-zero or a piped command fails. SHELL = /usr/bin/env bash -o pipefail @@ -92,13 +98,36 @@ build: manifests generate fmt vet ## Build manager binary. run: manifests generate fmt vet ## Run a controller from your host. go run ./cmd/main.go -.PHONY: ko-build -ko-build: ko ## Build docker image with the manager. - KO_DOCKER_REPO=$(KO_DOCKER_REPO) $(KO) build ./cmd --bare --sbom none --tags $(KO_DOCKER_TAG) --local - -.PHONY: ko-push -ko-push: ko ## Push docker image with the manager. - KO_DOCKER_REPO=$(KO_DOCKER_REPO) $(KO) build ./cmd --bare --sbom none --tags $(KO_DOCKER_TAG) +# If you wish to build the manager image targeting other platforms you can use the --platform flag. +# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. +# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +.PHONY: docker-build +docker-build: ## Build docker image with the manager. + $(CONTAINER_TOOL) build -t ${IMG} . + +.PHONY: docker-push +docker-push: ## Push docker image with the manager. + $(CONTAINER_TOOL) push ${IMG} + +# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple +# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: +# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/ +# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/ +# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=> then the export will fail) +# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option. +PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le +.PHONY: docker-buildx +docker-buildx: ## Build and push docker image for the manager for cross-platform support + # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile + sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross + - $(CONTAINER_TOOL) buildx create --name jumpstarter-controller-builder + $(CONTAINER_TOOL) buildx use jumpstarter-controller-builder + - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) \ + --tag ${DOCKER_REPO}:${DOCKER_TAG} \ + --tag ${DOCKER_REPO}:latest \ + -f Dockerfile.cross . + - $(CONTAINER_TOOL) buildx rm jumpstarter-controller-builder + rm Dockerfile.cross .PHONY: build-installer build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment. @@ -121,7 +150,7 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified $(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - .PHONY: deploy -deploy: ko-build cluster grpcurl +deploy: docker-build cluster grpcurl ./hack/deploy_with_helm.sh .PHONY: deploy-exporters @@ -151,7 +180,6 @@ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION) ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION) GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION) KIND = $(LOCALBIN)/kind-$(KIND_VERSION) -KO = $(LOCALBIN)/ko-$(KO_VERSION) GRPCURL = $(LOCALBIN)/grpcurl-$(GRPCURL_VERSION) ## Tool Versions @@ -160,7 +188,6 @@ CONTROLLER_TOOLS_VERSION ?= v0.16.3 ENVTEST_VERSION ?= release-0.18 GOLANGCI_LINT_VERSION ?= v1.61.0 KIND_VERSION ?= v0.23.0 -KO_VERSION ?= v0.17.0 GRPCURL_VERSION ?= v1.9.2 .PHONY: kustomize @@ -183,11 +210,6 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. $(GOLANGCI_LINT): $(LOCALBIN) $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION)) -.PHONY: ko -ko: $(KO) ## Download ko locally if necessary. -$(KO): $(LOCALBIN) - $(call go-install-tool,$(KO),github.com/google/ko,$(KO_VERSION)) - .PHONY: grpcurl grpcurl: $(GRPCURL) ## Download grpcurl locally if necessary. $(GRPCURL): $(LOCALBIN) diff --git a/README.md b/README.md index 4c3a61ae..ff320ad7 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ **Build and push your image to the location specified by `IMG`:** ```sh -make ko-push IMG=/jumpstarter-controller:tag +make docker-push IMG=/jumpstarter-controller:tag ``` **NOTE:** This image ought to be published in the personal registry you specified. diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index f604f0be..2d17e721 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -63,7 +63,7 @@ var _ = Describe("controller", Ordered, func() { var projectimage = "example.com/jumpstarter-router:v0.0.1" By("building the manager(Operator) image") - cmd := exec.Command("make", "ko-build", fmt.Sprintf("IMG=%s", projectimage)) + cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectimage)) _, err = utils.Run(cmd) ExpectWithOffset(1, err).NotTo(HaveOccurred())