Building a static Go binary with librdkafka on macOS
I’m writing this to hopefully save you the headache I went through today upgrading an app from confluent-kafka-go v0.11.x to v1.0.0.
Many thanks to Elias Levy for this post on github that helped me finally get a static build.
I’m on macOS but I’m targeting Linux. Normally I would just cross-compile but that is not possible since I’m creating a static binary against C libs.
Since I’m on macOS I’m using an Alpine Docker container to build against. Alpine doesn’t have the latest version of librdkafka available in the package repo so it has to be built from scratch. Additionally, libsasl poses difficulties as the static libs are not fully included. I need libsasl for this particular project as SASL is used to authenticate to the Kafka server.
First things first. Let’s create the base image that will be extended to build the project.
It’s important to note that specific features of libsasl like kerberos might not work using this method since they will need to be dynamically linked.
Now that the base is built, we can copy our source into a new image and build from it.
Finally, we can build our static Linux binary and export it from our container.
First build the base image, this will take a while.
docker build -t golang-static-base:1.11.4 -f buildbase.Dockerfile .
Now build the static go binary.
docker build -t app-build -f Dockerfile . && \
docker create --name app-container app-build && \
docker cp app-container:/go/src/app/app.o ./app.o && \
docker rm -f app-container && \
docker rmi -f app-build
This snippet builds an image that copies in the source and builds it. Then we create a container from that image called app-container. Finally we copy our binary out of the container and then clean up.
And there you have it.
$ file app.o
app.o: ELF 64-bit LSB executable, x86–64, version 1 (SYSV), statically linked, not stripped
All the source code is available here: https://github.com/jasongerard/go-librdkafka-static