diff --git a/Makefile b/Makefile index d177ec5d2..9d02775ab 100644 --- a/Makefile +++ b/Makefile @@ -34,11 +34,15 @@ PG_VERSION=11.9.8 DRACON_NS=dracon TEKTON_NS=tekton-pipelines ARANGODB_NS=arangodb -BASE_IMAGE=scratch DOCKER=docker PROTOC=protoc +# https://docs.docker.com/build/building/multi-platform/ +# Make sure to always build containers using AMD64 but allow to be overridden by users if need for cross-os compatibility. +GOOS=linux +GOARCH=amd64 + export ######################################## @@ -47,7 +51,7 @@ export .PHONY: components component-binaries cmd/draconctl/bin protos build publish-component-containers publish-containers draconctl-image draconctl-image-publish clean-protos clean $(component_binaries): - CGO_ENABLED=0 ./scripts/build_component_binary.sh $@ + GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 ./scripts/build_component_binary.sh $@ component-binaries: $(component_binaries) @@ -57,10 +61,10 @@ $(component_containers): %/docker: %/bin components: $(component_containers) cmd/draconctl/bin: - CGO_ENABLED=0 go build -o bin/cmd/draconctl cmd/draconctl/main.go + GOOS=darwin GOARCH=$(shell go env GOARCH) CGO_ENABLED=0 go build -o bin/cmd/draconctl cmd/draconctl/main.go draconctl-image: cmd/draconctl/bin - $(DOCKER) build -t "${CONTAINER_REPO}/draconctl:${DRACON_VERSION}" \ + $(DOCKER) build --platform $(GOOS)/$(GOARCH) -t "${CONTAINER_REPO}/draconctl:${DRACON_VERSION}" \ $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ -f containers/Dockerfile.draconctl . diff --git a/components/consumers/dependency-track/Dockerfile b/components/consumers/dependency-track/Dockerfile deleted file mode 100644 index 17a6cd3ae..000000000 --- a/components/consumers/dependency-track/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM alpine:3.20 - -RUN apk add --no-cache ca-certificates - -COPY ./components/consumers/dependency-track/dependency-track /app/components/consumers/dependency-track/dependency-track - -ENTRYPOINT ["/app/components/consumers/dependency-track/dependency-track"] diff --git a/components/consumers/dependency-track/Makefile b/components/consumers/dependency-track/Makefile deleted file mode 100644 index b160f0073..000000000 --- a/components/consumers/dependency-track/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: container publish - -CONTAINER_REPO= -DRACON_VERSION= -SOURCE_CODE_REPO= -PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch") - -DOCKER=docker - -container: - $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/dependency-track:$(DRACON_VERSION) \ - --file Dockerfile \ - $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ - ../../../bin 1>&2 - -publish: - $(DOCKER) push $(CONTAINER_REPO)/components/consumers/dependency-track:$(DRACON_VERSION) 1>&2 diff --git a/components/consumers/jira/Dockerfile b/components/consumers/jira/Dockerfile deleted file mode 100644 index 003b59928..000000000 --- a/components/consumers/jira/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM alpine:3.20 - -RUN apk add --no-cache ca-certificates - -COPY ./components/consumers/jira/jira /app/components/consumers/jira/jira - -ENTRYPOINT ["/app/components/consumers/jira/jira"] diff --git a/components/consumers/jira/Makefile b/components/consumers/jira/Makefile deleted file mode 100644 index bb2408a88..000000000 --- a/components/consumers/jira/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: container publish - -CONTAINER_REPO= -DRACON_VERSION= -SOURCE_CODE_REPO= -PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch") - -DOCKER=docker - -container: - $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/jira:$(DRACON_VERSION) \ - --file Dockerfile \ - $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ - ../../../bin 1>&2 - -publish: - $(DOCKER) push $(CONTAINER_REPO)/components/consumers/jira:$(DRACON_VERSION) 1>&2 diff --git a/components/consumers/slack/Dockerfile b/components/consumers/slack/Dockerfile deleted file mode 100644 index 8d0a1774e..000000000 --- a/components/consumers/slack/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM alpine:3.20 - -RUN apk add --no-cache ca-certificates - -COPY ./components/consumers/slack/slack /app/components/consumers/slack/slack - -ENTRYPOINT ["/app/components/consumers/slack/slack"] \ No newline at end of file diff --git a/components/consumers/slack/Makefile b/components/consumers/slack/Makefile deleted file mode 100644 index abf3c1326..000000000 --- a/components/consumers/slack/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: container publish - -CONTAINER_REPO= -DRACON_VERSION= -SOURCE_CODE_REPO= -PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch") - -DOCKER=docker - -container: - $(DOCKER) build --tag $(CONTAINER_REPO)/components/consumers/slack:$(DRACON_VERSION) \ - --file Dockerfile \ - $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ - ../../../bin 1>&2 - -publish: - $(DOCKER) push $(CONTAINER_REPO)/components/consumers/slack:$(DRACON_VERSION) 1>&2 diff --git a/components/producers/aggregator/Dockerfile b/components/producers/aggregator/Dockerfile index 3f74d3b26..618104b02 100644 --- a/components/producers/aggregator/Dockerfile +++ b/components/producers/aggregator/Dockerfile @@ -1,6 +1,9 @@ -ARG PRODUCER_AGGREGATOR_BASE_IMAGE -FROM ${PRODUCER_AGGREGATOR_BASE_IMAGE} +ARG BASE_IMAGE +FROM ${BASE_IMAGE:-scratch} -COPY ./components/producers/aggregator/aggregator-parser /app/components/producers/aggregator/tagger +ARG GOOS +ARG GOARCH + +COPY ./components/producers/aggregator/${GOOS}/${GOARCH}/aggregator-parser /app/components/producers/aggregator/tagger ENTRYPOINT ["/app/components/producers/aggregator/tagger"] diff --git a/components/producers/aggregator/Makefile b/components/producers/aggregator/Makefile index bc174363f..8f67eb3cc 100644 --- a/components/producers/aggregator/Makefile +++ b/components/producers/aggregator/Makefile @@ -3,15 +3,22 @@ CONTAINER_REPO= DRACON_VERSION= SOURCE_CODE_REPO= -PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch") + +# https://docs.docker.com/build/building/multi-platform/ +# Make sure to always build containers using AMD64 but allow to be overridden by users if need for cross-os compatibility. +GOOS=linux +GOARCH=amd64 DOCKER=docker container: $(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/tagger:$(DRACON_VERSION) \ + --platform $(GOOS)/$(GOARCH) \ + --build-arg GOOS=$(GOOS) \ + --build-arg GOARCH=$(GOARCH) \ --file Dockerfile \ $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ - --build-arg PRODUCER_AGGREGATOR_BASE_IMAGE=$(PRODUCER_AGGREGATOR_BASE_IMAGE) ../../../bin 1>&2 + --build-arg BASE_IMAGE=$(BASE_IMAGE) ../../../bin 1>&2 publish: $(DOCKER) push $(CONTAINER_REPO)/components/producers/tagger:$(DRACON_VERSION) 1>&2 diff --git a/components/producers/github-code-scanning/Dockerfile b/components/producers/github-code-scanning/Dockerfile index 8fe764be4..4895a0da2 100644 --- a/components/producers/github-code-scanning/Dockerfile +++ b/components/producers/github-code-scanning/Dockerfile @@ -1,7 +1,10 @@ FROM alpine:3.20 +ARG GOOS +ARG GOARCH + RUN apk add --no-cache ca-certificates -COPY ./components/producers/github-code-scanning/github-code-scanning-parser /app/components/producers/github-code-scanning/github-code-scanning-parser +COPY ./components/producers/github-code-scanning/${GOOS}/${GOARCH}/github-code-scanning-parser /app/components/producers/github-code-scanning/github-code-scanning-parser ENTRYPOINT ["/app/components/producers/github-code-scanning/github-code-scanning-parser"] diff --git a/components/producers/github-code-scanning/Makefile b/components/producers/github-code-scanning/Makefile index 949c455e1..b35791c57 100644 --- a/components/producers/github-code-scanning/Makefile +++ b/components/producers/github-code-scanning/Makefile @@ -3,15 +3,19 @@ CONTAINER_REPO= DRACON_VERSION= SOURCE_CODE_REPO= -PRODUCER_AGGREGATOR_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "scratch") + +# https://docs.docker.com/build/building/multi-platform/ +# Make sure to always build containers using AMD64 but allow to be overridden by users if need for cross-os compatibility. +GOOS=linux +GOARCH=amd64 DOCKER=docker container: $(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/github-code-scanning:$(DRACON_VERSION) \ + --platform $(GOOS)/$(GOARCH) \ + --build-arg GOOS=$(GOOS) \ + --build-arg GOARCH=$(GOARCH) \ --file Dockerfile \ $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ ../../../bin 1>&2 - -publish: - $(DOCKER) push $(CONTAINER_REPO)/components/producers/github-code-scanning:$(DRACON_VERSION) 1>&2 diff --git a/components/producers/ossf-scorecard/Dockerfile b/components/producers/ossf-scorecard/Dockerfile index d81c6bc86..ef4096e77 100644 --- a/components/producers/ossf-scorecard/Dockerfile +++ b/components/producers/ossf-scorecard/Dockerfile @@ -1,8 +1,3 @@ -ARG OSSF_SCORECARD_SAFETY_BASE_IMAGE FROM gcr.io/openssf/scorecard:stable -FROM ${OSSF_SCORECARD_SAFETY_BASE_IMAGE} - -COPY --from=0 /scorecard /scorecard - -ENTRYPOINT ["/scorecard"] \ No newline at end of file +ENTRYPOINT ["/scorecard"] diff --git a/components/producers/ossf-scorecard/Makefile b/components/producers/ossf-scorecard/Makefile index e93faa1f5..ccc8e9de9 100644 --- a/components/producers/ossf-scorecard/Makefile +++ b/components/producers/ossf-scorecard/Makefile @@ -2,7 +2,7 @@ CONTAINER_REPO= DRACON_VERSION= -OSSF_SCORECARD_SAFETY_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "alpine:latest") +OSSF_SCORECARD_SAFETY_BASE_IMAGE="alpine:latest" DOCKER=docker diff --git a/components/producers/typescript-eslint/eslint-wrapper/Dockerfile b/components/producers/typescript-eslint/eslint-wrapper/Dockerfile index 134be31fd..71260b1e8 100644 --- a/components/producers/typescript-eslint/eslint-wrapper/Dockerfile +++ b/components/producers/typescript-eslint/eslint-wrapper/Dockerfile @@ -1,10 +1,13 @@ ARG ESLINT_WRAPPER_BASE_IMAGE -FROM ${ESLINT_WRAPPER_BASE_IMAGE} +FROM ${ESLINT_WRAPPER_BASE_IMAGE:-node:lts} + +ARG GOOS +ARG GOARCH WORKDIR /home/node/workspace COPY components/producers/typescript-eslint/eslint-wrapper/eslintrc.js /home/node/workspace COPY components/producers/typescript-eslint/eslint-wrapper/package.json /home/node/workspace -COPY bin/components/producers/typescript-eslint/eslint-wrapper/eslint-wrapper-parser /home/node/workspace/ +COPY bin/components/producers/typescript-eslint/eslint-wrapper/${GOOS}/${GOARCH}/eslint-wrapper-parser /home/node/workspace/ RUN npm uninstall --save bcrypt &&\ npm install --save-dev \ diff --git a/components/producers/typescript-eslint/eslint-wrapper/Makefile b/components/producers/typescript-eslint/eslint-wrapper/Makefile index a4e344bfc..fe9c778a5 100644 --- a/components/producers/typescript-eslint/eslint-wrapper/Makefile +++ b/components/producers/typescript-eslint/eslint-wrapper/Makefile @@ -2,12 +2,19 @@ CONTAINER_REPO= DRACON_VERSION= -ESLINT_WRAPPER_BASE_IMAGE=$(shell test -e .custom_image && cat .custom_image || echo "node:lts") + +# https://docs.docker.com/build/building/multi-platform/ +# Make sure to always build containers using AMD64 but allow to be overridden by users if need for cross-os compatibility. +GOOS=linux +GOARCH=amd64 DOCKER=docker container: $(DOCKER) build --tag $(CONTAINER_REPO)/components/producers/typescript-eslint/eslint-wrapper:$(DRACON_VERSION) \ + --platform $(GOOS)/$(GOARCH) \ + --build-arg GOOS=$(GOOS) \ + --build-arg GOARCH=$(GOARCH) \ --file Dockerfile \ $$([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ --build-arg ESLINT_WRAPPER_BASE_IMAGE=$(ESLINT_WRAPPER_BASE_IMAGE) ../../../.. 1>&2 diff --git a/containers/Dockerfile.base b/containers/Dockerfile.base new file mode 100644 index 000000000..5f3c57bae --- /dev/null +++ b/containers/Dockerfile.base @@ -0,0 +1,21 @@ +FROM golang:alpine AS builder + +ARG EXECUTABLE_SRC_PATH +ARG EXECUTABLE_TARGET_PATH +ENV EXECUTABLE_TARGET_PATH=${EXECUTABLE_TARGET_PATH} +COPY ${EXECUTABLE_SRC_PATH} /app/${EXECUTABLE_TARGET_PATH} + +RUN apk update && \ + apk upgrade && \ + apk add --no-cache ca-certificates && \ + update-ca-certificates && \ + ln -s /app/${EXECUTABLE_TARGET_PATH} /bin/component + +FROM scratch + +ARG EXECUTABLE_TARGET_PATH +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ +COPY --from=builder /app/${EXECUTABLE_TARGET_PATH} /app/${EXECUTABLE_TARGET_PATH} +COPY --from=builder /bin/component /bin/component + +ENTRYPOINT ["/bin/component"] diff --git a/containers/Dockerfile.base.image b/containers/Dockerfile.base.image new file mode 100644 index 000000000..aa83bcb1c --- /dev/null +++ b/containers/Dockerfile.base.image @@ -0,0 +1,4 @@ +FROM ${BASE_IMAGE:-scratch} +ARG executable_path +COPY ${executable_path} /app/${executable_path} +ENTRYPOINT ["/app/${executable_path}"] diff --git a/scripts/build_component_binary.sh b/scripts/build_component_binary.sh index 64d97e651..9e415d74d 100755 --- a/scripts/build_component_binary.sh +++ b/scripts/build_component_binary.sh @@ -19,6 +19,9 @@ echo "${1}" | grep -Eq ^components/consumers/.*$ && executable="${executable}" | executable_src_path=$(dirname "${1}") executable_path=$(dirname $(dirname "${1}"))/"${executable}" -echo "building bin/${executable_path}/${executable}" > /dev/stderr +# Customised bin per OS/ARCH. +out_bin_path="bin/${executable_src_path}/${GOOS}/${GOARCH}/${executable}" -go build -o "bin/${executable_src_path}/${executable}" "./${executable_src_path}/main.go" +echo "building $out_bin_path" > /dev/stderr + +go build -o $out_bin_path "./${executable_src_path}/main.go" diff --git a/scripts/build_component_container.sh b/scripts/build_component_container.sh index 2ad5e8d9e..5decfc650 100755 --- a/scripts/build_component_container.sh +++ b/scripts/build_component_container.sh @@ -16,23 +16,23 @@ echo "${1}" | grep -Eq ^components/producers/.*$ && executable="${executable}-pa echo "${1}" | grep -Eq ^components/enrichers/.*$ && executable="${executable}" || true echo "${1}" | grep -Eq ^components/consumers/.*$ && executable="${executable}" || true +container_platform=${GOOS}/${GOARCH} executable_src_path=$(dirname "${1}") -executable_path=$(dirname "${1}")/"${executable}" +executable_path=$(dirname "${1}")/"${container_platform}/${executable}" + +BASE_IMAGE_PATH=$(realpath ${BASE_IMAGE_PATH:-./containers/Dockerfile.base}) if make -C "${executable_src_path}" --no-print-directory --dry-run container >/dev/null 2>&1 then - make -C "${executable_src_path}" --no-print-directory --quiet container CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}" + make -C "${executable_src_path}" --no-print-directory --quiet container BASE_IMAGE_PATH="${BASE_IMAGE_PATH}" CONTAINER_REPO="${CONTAINER_REPO}" DRACON_VERSION="${DRACON_VERSION}" else - dockerfile_template=" - FROM ${BASE_IMAGE:-scratch} \n - COPY ${executable_path} /app/${executable_path} \n - ENTRYPOINT ["/app/${executable_path}"] \n - " - dockerfile_path=$(mktemp) - printf "${dockerfile_template}" > "${dockerfile_path}" - docker build -t "${CONTAINER_REPO}/${executable_src_path}:${DRACON_VERSION}" \ + docker build \ + --platform "${container_platform}" \ + --build-arg EXECUTABLE_SRC_PATH=${executable_path} \ + --build-arg EXECUTABLE_TARGET_PATH=${executable_path} \ + -t "${CONTAINER_REPO}/${executable_src_path}:${DRACON_VERSION}" \ $([ "${SOURCE_CODE_REPO}" != "" ] && echo "--label=org.opencontainers.image.source=${SOURCE_CODE_REPO}" ) \ - -f "${dockerfile_path}" ./bin + -f "${BASE_IMAGE_PATH}" ./bin fi if make -C "${executable_src_path}" --no-print-directory --dry-run extras >/dev/null 2>&1