diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b2e14ab..c61df30 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -47,6 +47,7 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
+ - uses: docker/setup-qemu-action@v3 # arm64 runtime stage runs apt-get under emulation
- uses: docker/setup-buildx-action@v3
- name: Login to GHCR
@@ -56,11 +57,11 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build & push public image (amd64 — Scaleway requires it)
+ - name: Build & push public image (amd64 for Scaleway + arm64 for local dev)
uses: docker/build-push-action@v6
with:
context: .
- platforms: linux/amd64
+ platforms: linux/amd64,linux/arm64
push: true
build-args: |
VERSION=${{ github.sha }}
diff --git a/Dockerfile b/Dockerfile
index 09a1012..7ae000a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,14 +3,18 @@
# runtime image needs only git.
# syntax=docker/dockerfile:1
-FROM golang:1.26-alpine AS build
+# The build stage runs on the native BUILDPLATFORM and cross-compiles to
+# TARGET* (Go is pure-Go/CGO_ENABLED=0), so a multi-arch build never emulates
+# the compiler — only the runtime stage's apt-get runs under QEMU.
+FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
ARG VERSION=docker
-RUN CGO_ENABLED=0 go build -ldflags "-X main.version=${VERSION}" -o /out/gitmote ./cmd/gitmote \
- && CGO_ENABLED=0 go build -o /out/gitmote-hook ./cmd/gitmote-hook
+ARG TARGETOS TARGETARCH
+RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-X main.version=${VERSION}" -o /out/gitmote ./cmd/gitmote \
+ && CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/gitmote-hook ./cmd/gitmote-hook
# Debian's git package includes git-http-backend (Alpine's splits it out); the
# whole design delegates to `git http-backend`, so it must be present.