|home| |posts| |projects| |cv| |bookmarks| |github|

Use Alpine Linux to Create Static Binaries for Cgo Programs

Go programs that use cgo(e.g. those that use sqlite) break one of the best features of go: static binaries.

Usually, C programs can be made static by passing the -static flag to the compiler/linker.

In Go we can do that like this:

go build -ldflags '-extldflags "-static"'

This works if the C code doesn't use any shared libraries(.so) or, if it does, there are static versions(.a) on your system for those libs.

But if those conditions aren't met(for example if the program links against libdl), that means that your Go binary will be dynamically linked.

But there's a way to avoid it.

You can use Alpine Linux, which uses musl libc(which has no external dependencies), to compile your Go program.

Alpine is a Linux distro, so that means that this trick works only for Linux. This won't work for other platforms.

Here's how it can be done:

docker run --rm --name alpine_builder golang:alpine sleep infinity
docker cp main.go alpine_builder:/tmp/
docker exec -it alpine_builder ash
cd /tmp
go build -ldflags '-extldflags "-static"' -o my_binary main.go
docker cp alpine_builder:/tmp/my_binary .
docker stop alpine_builder

You can check if it worked with

ldd my_binary

It should print something like this: not a dynamic executable.

After all this, you now have your statically linked binary(my_binary) that you can use on your machine or copy to any Linux machine.