Skip to content

Commit

Permalink
Multi arch docker build (#123)
Browse files Browse the repository at this point in the history
* Multi arch docker build

Signed-off-by: Faisal Memon <[email protected]>

* Make go version arg in dockerfile

Signed-off-by: Faisal Memon <[email protected]>

---------

Signed-off-by: Faisal Memon <[email protected]>
  • Loading branch information
faisal-memon authored Jan 12, 2024
1 parent 8d4d3ab commit 3f6ea7f
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 8 deletions.
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 []
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

0 comments on commit 3f6ea7f

Please sign in to comment.