Graft the Golang Toolchain Onto the Base Image You Need
When the Docker Hub tag matrix lacks your Golang and Alpine combination, a multi-stage build grafts the toolchain onto a different base, but verify the need is real first.
When the Docker Hub tag matrix genuinely doesn’t have the Golang × Alpine combination you need (see Query the tag matrix first), a multi-stage build (a Dockerfile with multiple FROM lines, each its own build step) lets you copy the Golang toolchain from one stage into a different base. The two FROM lines are siblings, not a chain. The last one is the base that ships:
FROM golang:1.25-alpine AS gotool # take ONLY the toolchain
FROM alpine:3.20 # choose the syslib version you need
COPY --from=gotool /usr/local/go /usr/local/go
ENV PATH=/usr/local/go/bin:$PATH
ENV GOTOOLCHAIN=local # don't let go re-fetch a toolchain
RUN apk add vips-dev # → Go 1.25 + chosen libvips, independently
GOTOOLCHAIN=localstopsgofrom auto-downloading a toolchain to satisfy a highergo.moddirective.- Pin both the build and runtime stages to the same base, or the runtime silently ships the wrong syslibs.
- Watch the graft’s own coupling: a floating
golang:<v>-alpinetoolchain built against a newer musl (Alpine’s C standard library), grafted onto an older base, can cause library version mismatches.
When NOT to reach for this: Two gates, in order: (1) check the matrix, the combo may already be published; (2) verify the syslib need is real. A graft built on a false “I need the older lib” premise is pure complexity.
A graft solves “the matrix doesn’t have my combination.” If your premise is “I need an older library,” verify that need is real before building the complexity.
Sources:
- https://docs.docker.com/guides/golang/build-images/
- https://github.com/alextanhongpin/go-docker-multi-stage-build
Related: Back to the chain reaction overview, or see query the tag matrix first, pinning with an exit plan, or EOL base image risks.