golang構建程式很簡單,當遇到需要呼叫c庫時,如通常使用 net
,kafka
, sqlite3
程式執行時就會呼叫當前伺服器的 動態庫,如果遇到沒有庫時,通常還需要 下載比如 alpine需要安裝sqlite
apk add --no-cache sqlite-libs sqlite-dev
通常我們構建時使用CGO_ENABLED=1
就能在構建時將程式碼需要呼叫C庫用動態連線的形勢供程式碼呼叫
CGO_ENABLED=1 go build -ldflags "-s -w" -o perception_node ./cmd/
但是這裡面會有個問題,如果將編譯好的 二進位制檔案移植到其他伺服器,但是伺服器上面的動態庫版本又和構建時的動態庫版本不一樣, 或者動態庫的路徑不一樣。可能有想到,升級c庫,或降低版本。但是一旦升級或降級C庫,很可能導致伺服器上原來的服務受影響。
如何解決:
綜上所述,使用最新的映象來編譯,但是會依賴所有的靜態連結,這樣一編譯完成後就不用擔心c庫相容的問題, 如果使用 glibc,則它不是靜態可連結的。
因為 glibc 依賴於支援不同提供程式的 libnss,所以它必須動態連結。
所以這裡替換glibc的唯一方法就是使用musl。librdkafka
和 golang 包confluent-kafka-go
都支援 musl 構建(構建時指定 –tags musl
即可) alpine
是基於 musl
的發行版,所以這裡可以直接用 alpine Linux
構建。
然後指定外部 ld
和-staticfor
標誌,編譯後的二進位制檔案將完全靜態連結。編譯過程如下。
$ docker run -it -v $(pwd):/workspace golang:1.18-alpine
/go $ cd /workspace/
/workspace $ sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
> apk add git openssh make build-base alpine-sdk
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/37) Installing fakeroot (1.25.3-r3)
(2/37) Installing openssl (1.1.1l-r0)
(3/37) Installing libattr (2.5.1-r0)
(4/37) Installing attr (2.5.1-r0)
(5/37) Installing libacl (2.2.53-r0)
(6/37) Installing tar (1.34-r0)
(7/37) Installing pkgconf (1.7.4-r0)
...
$ export GOPROXY="https://goproxy.cn"
/workspace $ go build -ldflags "-linkmode external -extldflags '-static'" -tags musl -o perception_node ./cmd/
/workspace $ ldd perception_node
/lib/ld-musl-x86_64.so.1: spex: Not a valid dynamic program
windows下使用如下指令
$ docker run -it -v $(pwd):/workspace golang:1.18-alpine
/go $ cd /workspace/
/workspace $ sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
$ apk add openssh make build-base alpine-sdk mingw-w64-gcc musl-dev gcc build-base
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/37) Installing fakeroot (1.25.3-r3)
(2/37) Installing openssl (1.1.1l-r0)
(3/37) Installing libattr (2.5.1-r0)
(4/37) Installing attr (2.5.1-r0)
(5/37) Installing libacl (2.2.53-r0)
(6/37) Installing tar (1.34-r0)
(7/37) Installing pkgconf (1.7.4-r0)
...
$ export GOPROXY="https://goproxy.cn"
$ CGO_ENABLED=1 GOOS=windows CC=x86_64-w64-mingw32-gcc go build -ldflags "-linkmode external -extldflags '-static'" -tags musl -o seduce_node_agent.exe main.go