Go: Static linking with CGO and distroless
One of the nice things about Go is that, by default, it compiles to a statically
linked binary with no external dependencies (including shared libraries). This
makes it super easy to deploy, and you can use a basically empty docker image
(like distroless).
However, if you have CGO_ENABLED=1 (which is required for some libraries, such
as the C based sqlite bindings), it will link everything statically except
libc by default. When using distroless, you usually compile on an image that
has libc, but then copy the binary to an image that doesn't, so while
compilation doesn't fail, the binary cannot find libc and will not run.
You can remedy this by statically linking libc by passing
-ldflags '-s -w -linkmode external -extldflags "-static"' to go build like
so:
$ go build -a \
-ldflags '-s -w -linkmode external -extldflags "-static"' \
./...
A couple things to note about this method:
- It will take quite a bit longer to compile
- The resulting file will be a lot larger
- This will NOT work if you use the Go plugin system (
dlopendoesn't work)
Good luck!