docker 映象的一次瘦身

地球沒有花發表於2018-11-20

環境: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目錄下找所引用到的,有待探索)。其次引數-ldflags '-s -w'的意思是,首先ldflags是用於給編譯時候傳引數的,這裡傳的是-s和-w,意思是去掉debug的資訊,減少檔案的冗餘資料(效果還是很明顯的)。

對於我們docker的scratch映象來說,我們只需要最小能提供服務的環境需要,而且容器只用來提供服務,不在上面操作什麼,所以把此時生成的二進位制包打包進scratch並tag版本,上傳到公司的hub。

 

本文只是一個“瘦身”的實踐,理論部分,原理部分可以自己搜。

參考:

這篇白大的文章很不錯,深度好文。也談Go的可移植性

這篇英文的,看看前面那部分,講build的幾個引數,包括-w和-extldflags "-static"。On Golang, “static” binaries, cross-compiling and plugins

這個是一些go build的引數,可能還有能“瘦身”的命令,只是我還不知道。Compile packages and dependencies

這個是對ldflags命令的一個生動的例子。Setting Go variables from the outside

這個是stackoverflow的提問,關於-w的用途。Avoid debugging information on golang

這個是官方的ldflags的引數。command line

這個是幫助“瘦身”的方法,可以看看。Shrink your Go binaries with this one weird trick

這個文章是最開始的時候受的啟發,很感謝。What is a Docker container?

這個csdn的提問也可以看一下。給golang程式進行一次廋身

 

 

 

 

 

 

相關文章