Build a static binary
Build a statically linked Go binary with CGO_ENABLED=0. Programs that import net link to libc by default when a C compiler is present, which breaks on Alpine.
A Go binary built on Debian crashes on Alpine or in a scratch image with "not found", because it depends on a C library the target does not have.
package main
import (
"fmt"
"net"
)
func main() {
fmt.Println(net.ParseIP("10.0.0.1"))
}go build -o dynamic main.go
CGO_ENABLED=0 go build -o static main.go
ldd dynamic | head -2
ldd static linux-vdso.so.1 (0x0000ffff94e06000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff94c10000)
not a dynamic executableThe net and os/user packages have a cgo implementation that calls the C resolver, and the go tool uses it whenever a C compiler is found and CGO_ENABLED is not 0. The first binary therefore links against libc. Setting the variable to 0 selects the pure Go implementation, as the cgo documentation describes, and ldd confirms the second binary needs nothing.
With cgo off, the DNS resolver and user lookups use the pure Go code, which can behave differently from the system resolver with unusual nsswitch.conf setups. Libraries that need C, like SQLite drivers based on the C source, will not build. Output here is from Go 1.19 on Debian 12.