From 93860c9db03e0d39cde3762a299a6f1370c6401d Mon Sep 17 00:00:00 2001 From: Maor Davidov Date: Sun, 27 Sep 2026 23:31:15 +0300 Subject: [PATCH] build(docker): multi-arch rootless image (linux/amd64 + linux/arm64) The finoptic-internal EKS cluster is moving to Graviton (arm64), and dcodetech/gitea:v1.20-dcode.3-rootless is amd64-only. Dockerfile.rootless now runs its build stage on the build host's platform and cross-compiles the gitea binary (cgo, for sqlite) with tonistiigi/xx, so a two-platform build needs no emulated Go or node toolchain. The frontend and go generate/bindata steps are platform-independent and run once, natively. The runtime stage is unchanged. GITEA_BUILD_VERSION sets the version string when the build context has no usable .git directory (a git worktree). The new docker-multiarch make target builds and pushes both platforms. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_014NcddqY43b3wAdjBdjcnFf --- Dockerfile.rootless | 32 +++++++++++++++++++++++++------- Makefile | 11 ++++++++++- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/Dockerfile.rootless b/Dockerfile.rootless index aa74d3598750a..7057976c491e3 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,5 +1,13 @@ +# Multi-arch build (linux/amd64 + linux/arm64) without an emulated toolchain. +# The build stage always runs on the build host's own platform ($BUILDPLATFORM): +# the frontend and the generated Go sources are platform-independent, and the +# gitea binary is cross-compiled for $TARGETPLATFORM with tonistiigi/xx +# (clang + a target musl sysroot; cgo is needed for sqlite). Only the small +# runtime stage below runs as the target platform. +FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx:1.6.1 AS xx + #Build stage -FROM docker.io/library/golang:1.20-alpine3.18 AS build-env +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20-alpine3.18 AS build-env ARG GOPROXY ENV GOPROXY ${GOPROXY:-direct} @@ -10,18 +18,28 @@ ENV TAGS "bindata timetzdata $TAGS" ARG CGO_EXTRA_CFLAGS #Build deps -RUN apk --no-cache add build-base git nodejs npm +RUN apk --no-cache add build-base git nodejs npm clang lld +COPY --from=xx / / #Setup repo COPY . ${GOPATH}/src/code.gitea.io/gitea WORKDIR ${GOPATH}/src/code.gitea.io/gitea -#Checkout version if set +#Checkout version if set, then build everything that does not depend on the +#target platform (frontend assets + go generate / bindata) natively, once. RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \ - && make clean-all build - -# Begin env-to-ini build -RUN go build contrib/environment-to-ini/environment-to-ini.go + && make clean-all frontend go-check generate-backend + +#Cross-compile the backend and env-to-ini for the target platform +ARG TARGETPLATFORM +RUN xx-apk add --no-cache gcc musl-dev +# Version string baked into the binary. By default the Makefile takes it from +# `git describe`; pass it when the build context has no usable .git directory +# (a git worktree, for example), e.g. GITEA_BUILD_VERSION=1.20.3+10-gabcdef012 +ARG GITEA_BUILD_VERSION +RUN CGO_ENABLED=1 make GO=xx-go ${GITEA_BUILD_VERSION:+GITEA_VERSION=$GITEA_BUILD_VERSION} gitea \ + && CGO_ENABLED=1 xx-go build contrib/environment-to-ini/environment-to-ini.go \ + && xx-verify gitea environment-to-ini FROM docker.io/library/alpine:3.18 LABEL maintainer="maintainers@gitea.io" diff --git a/Makefile b/Makefile index ec678a93d95b2..399341023de8b 100644 --- a/Makefile +++ b/Makefile @@ -1007,9 +1007,18 @@ generate-manpage: @gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created @#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page +DOCKER_PLATFORMS ?= linux/amd64,linux/arm64 + .PHONY: docker docker: - docker build -t $(DOCKER_REF) -f Dockerfile.rootless . + docker build --build-arg GITEA_BUILD_VERSION=$(GITEA_VERSION) -t $(DOCKER_REF) -f Dockerfile.rootless . + +# amd64 + arm64 image, pushed straight to the registry (a multi-platform image +# cannot be loaded into the local image store). Always use a new DOCKER_TAG: +# make docker-multiarch DOCKER_IMAGE=dcodetech/gitea DOCKER_TAG=v1.20-dcode.N +.PHONY: docker-multiarch +docker-multiarch: + docker buildx build --platform $(DOCKER_PLATFORMS) --build-arg GITEA_BUILD_VERSION=$(GITEA_VERSION) -t $(DOCKER_REF) -f Dockerfile.rootless --push . # support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" . # This endif closes the if at the top of the file