docker 映象的一次瘦身
環境:go1.10
結果:映象從200m瘦身到10.2m,上傳到harbor後是3.5m。下圖是上傳到harbor的,也就是壓縮後的。
總的思路:
1、瘦映象。這個好說,換個小點的映象就行。
2、瘦go。這個需要對go的編譯過程有些瞭解。
服務容器化,用docker和go是最合適的。go可以靜態編譯好之後只把二進位制檔案上傳到映象便可提供服務,實現了“一次編譯,處處執行”。
從網上拉了一個centos的映象,上傳完二進位制檔案後,打包一看700m+,太大了。
後來瞭解到一個scratch的空映象,啥都沒有,包括各種命令,都沒有,只有最基本的核心包。是一個純粹的“平臺”,這對於go來說最好不過了,只在純粹的平臺上提供純粹的微服務,過著純粹的生活。
“go build -o foo main.go” VS “CGO_ENABLED=0 go build -a -ldflags '-s -w' -o foo_total_static main.go”
分別生成個名為foo和foo_total_static的二進位制檔案。
分別 ldd foo 和 ldd foo_total_static 會分別輸出如下:
$ ldd foo linux-vdso.so.1 => (0x00007ffc95fde000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd150f27000) libc.so.6 => /lib64/libc.so.6 (0x00007fd150b93000) /lib64/ld-linux-x86-64.so.2 (0x00007fd151156000) $ ldd foo_total_static not a dynamic executable
什麼意思,ldd是檢視程式所用到的動態庫的命令。由此可以看出,go的build這個命令預設編譯出來的foo並不是完全靜態編譯的,它還是需要那些動態庫的;而“CGO_ENABLED=0 go build -a -ldflags '-s -w' -o foo_total_static main.go”命令,首先上來把cgo ban掉(至少我的程式裡是沒用到cgo的,所以我要ban掉,),然後執行了 go build -a -ldflags '-s -w',這個命令的引數的意思是:-a就是重新構建程式碼包(我個人感覺可能是“強刷ctrl+f5”的感覺,因為我發現-n的時候,有的編譯過程會直接去~/.cache/go-build目錄下找所引用到的,
對於我們docker的scratch映象來說,我們只需要最小能提供服務的環境需要,而且容器只用來提供服務,不在上面操作什麼,所以把此時生成的二進位制包打包進scratch並tag版本,上傳到公司的hub。
本文只是一個“瘦身”的實踐,理論部分,原理部分可以自己搜。
參考:
這篇白大的文章很不錯,深度好文。也談Go的可移植性
這個是官方的ldflags的引數。command line