Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi arch docker build #123

Merged
merged 5 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/workflows/scripts/load-oci-archives.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bash
# shellcheck shell=bash
##
## USAGE: __PROG__
##
## "__PROG__" loads oci tarballs created with xbuild into docker.
##
## Usage example(s):
## ./__PROG__
## PLATFORM=linux/arm64 ./__PROG__
##
## Commands
## - ./__PROG__ loads the oci tarball into Docker.

function usage {
grep '^##' "$0" | sed -e 's/^##//' -e "s/__PROG__/$me/" >&2
}

function normalize_path {
# Remove all /./ sequences.
local path=${1//\/.\//\/}
local npath
# Remove first dir/.. sequence.
npath="${path//[^\/][^\/]*\/\.\.\//}"
# Remove remaining dir/.. sequence.
while [[ $npath != "$path" ]] ; do
path=$npath
npath="${path//[^\/][^\/]*\/\.\.\//}"
done
echo "$path"
}

me=$(basename "$0")
BASEDIR=$(dirname "$0")
ROOTDIR="$(normalize_path "$BASEDIR/../../../")"

command -v regctl >/dev/null 2>&1 || { usage; echo -e "\n * The regctl cli is required to run this script." >&2 ; exit 1; }
command -v docker >/dev/null 2>&1 || { usage; echo -e "\n * The docker cli is required to run this script." >&2 ; exit 1; }

# Takes the current platform architecture or plaftorm as defined externally in a platform variable.
# e.g.:
# linux/amd64
# linux/arm64
PLATFORM="${PLATFORM:-local}"
OCI_IMAGES=(
spiffe-helper
)

org_name=$(echo "$GITHUB_REPOSITORY" | tr '/' "\n" | head -1 | tr -d "\n")
org_name="${org_name:-spiffe}" # default to spiffe in case ran on local
registry=ghcr.io/${org_name}

echo "Importing ${OCI_IMAGES[*]} into docker".
for img in "${OCI_IMAGES[@]}"; do
oci_dir="ocidir://${ROOTDIR}oci/${img}"
platform_tar="${img}-${PLATFORM}-image.tar"
image_to_load="${registry}/${img}:devel"

# regclient works with directories rather than tars, so import the OCI tar to a directory
regctl image import "$oci_dir" "${img}-image.tar"
dig="$(regctl image digest --platform "$PLATFORM" "$oci_dir")"
# export the single platform image using the digest
regctl image export "$oci_dir@${dig}" "${platform_tar}"

docker load < "${platform_tar}"
docker image tag "localhost/oci/${img}:latest" "${image_to_load}"
docker image rm "localhost/oci/${img}:latest"
done
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ rpm/*.rpm
*.swp
*.swo
bootstrap.crt

# oci image builds
oci/
*-image.tar
44 changes: 37 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
FROM golang
# Build the spiffe-helper binary
ARG go_version
FROM --platform=$BUILDPLATFORM golang:${go_version}-alpine as base
WORKDIR /workspace

WORKDIR /build
COPY . /build
RUN CGO_ENABLED=0 go build -o spiffe-helper ./cmd/spiffe-helper
# 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
COPY go.* ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download

# Copy the go source
COPY cmd/spiffe-helper/main.go cmd/spiffe-helper/main.go
COPY pkg/ pkg/

# xx is a helper for cross-compilation
# when bumping to a new version analyze the new version for security issues
# then use crane to lookup the digest of that version so we are immutable
# crane digest tonistiigi/xx:1.3.0
FROM --platform=${BUILDPLATFORM} tonistiigi/xx@sha256:904fe94f236d36d65aeb5a2462f88f2c537b8360475f6342e7599194f291fb7e AS xx

FROM --platform=${BUILDPLATFORM} base as builder
ARG TARGETPLATFORM
ARG TARGETARCH

ENV CGO_ENABLED=0
COPY --link --from=xx / /
RUN xx-go --wrap
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
go build -o bin/spiffe-helper cmd/spiffe-helper/main.go

# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
#FROM gcr.io/distroless/static:nonroot
FROM gcr.io/distroless/static AS spiffe-helper
WORKDIR /
COPY --link --from=builder /workspace/bin/spiffe-helper /spiffe-helper

FROM scratch
COPY --from=0 /build/spiffe-helper /spiffe-helper
ENTRYPOINT ["/spiffe-helper"]
CMD ["-config", "/etc/spiffe-helper.conf"]
CMD []
faisal-memon marked this conversation as resolved.
Show resolved Hide resolved
28 changes: 27 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export GO111MODULE=on
DIR := ${CURDIR}
PLATFORMS ?= linux/amd64,linux/arm64

E:=@
ifeq ($(V),1)
Expand Down Expand Up @@ -41,6 +42,15 @@ help:
@echo "For verbose output set V=1"
@echo " for example: $(cyan)make V=1 build$(reset)"

# Used to force some rules to run every time
.PHONY: FORCE
FORCE: ;

# 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

############################################################################
# OS/ARCH detection
Expand Down Expand Up @@ -167,11 +177,27 @@ lint-code: $(golangci_lint_bin) | go-check
# Build targets
############################################################################

.PHONY: build test clean distclean artifact tarball rpm
.PHONY: build test clean distclean artifact tarball rpm docker-build container-builder load-images

build: | go-check
go build -o spiffe-helper${exe} ./cmd/spiffe-helper

docker-build: $(addsuffix -image.tar, spiffe-helper) ## Build docker image with spiffe-helper.

container-builder: ## Create a buildx node to create crossplatform images.
$(CONTAINER_TOOL) buildx create --platform $(PLATFORMS) --name container-builder --node container-builder0 --use

spiffe-helper-image.tar: Dockerfile FORCE | container-builder
$(CONTAINER_TOOL) buildx build \
--platform $(PLATFORMS) \
--build-arg go_version=$(go_version) \
--target spiffe-helper \
-o type=oci,dest=$@ \
.

load-images: $(addsuffix -image.tar,$(BINARIES)) ## Load the image for your current PLATFORM into docker from the cross-platform oci tar.
./.github/workflows/scripts/load-oci-archives.sh

artifact: tarball rpm

tarball: build
Expand Down
Loading