golangで書いたアプリケーションのstatic link化

「goで書いたアプリケーションは実行ファイルひとつコピーするだけでいいのでインスコ超ラクチン」なんて思ってたんですが、 go1.4からnetパッケージを使っているアプリケーションは、フツーにビルドするとdynamic linkになるようになってました。

$ cd /path/to/your_app
$ go build
$ file your_app
your_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

そんなわけで別環境にバイナリコピーしても動かないケースが発生して超絶アタマを悩ませることになるのですが、 そんなときは以下のようにbuildすればstatic linkになってくれるようです。

$ go build -a -tags netgo -installsuffix netgo
$ file your_app
your_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

参考 https://github.com/golang/go/issues/9369

cgoを完全に使ってない場合は以下のようにcgoを無効化してビルドしてもstatic linkになります。

$ CGO_ENABLED=0 go build
$ file your_app
your_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

なお、アプリケーションやライブラリ側でcgo使ってる場合は、glibcの関係でそれでもdynamic linkになります。 でも以下のようにstatic linkするようにオプションを追加してあげればOKです。

$ go build -a -tags netgo -installsuffix netgo --ldflags '-extldflags "-static"'

# CentOSの場合、glibc-staticがインスコされてないと、ldでコケます。

build後のバイナリを配布したいとか、dockerでalpineにバイナリコピーしてイメージ作ったんだけど動かねぇ……とかっていう場合にどーぞー。