關(guān)于我們

質量為(wèi)本、客戶為(wèi)根、勇于拼搏、務(wù)實創新(xīn)

< 返回新(xīn)聞公共列表

怎麽為(wèi)Go程序創建一(yī)個(gè)最小的Docker Image

發布時(shí)間(jiān):2021-04-01 16:41:25

這(zhè)篇文章是關(guān)于如(rú)何為(wèi)Go程序創建一(yī)個(gè)最小的Docker映像。微子(zǐ)網絡覺得很實用,就(jiù)分(fēn)享給大家參考,跟着微子(zǐ)網絡看了(le)看。

前言

之前介紹了(le)關(guān)于在docker部署golang項目的相關(guān)内容,對你入門有一(yī)定的參考價值。本文将向您介紹如(rú)何使用docker來(lái)打包golang編寫的應用程序,最終産品是一(yī)個(gè)Dockerfile。不要小看這(zhè)短短的幾行代碼,其中涉及到很多知識點。接下(xià)來(lái)我們仔細分(fēn)析一(yī)下(xià)。

來(lái)自德國:阿爾卑斯山

ADDsrc/go/src

RUNgoinstall-vtest

ENTRYPOINT['/go/bin/test']

1. 基礎鏡像選擇

第一(yī)行是指定一(yī)個(gè)基本圖像,并基于它創建我們的圖像。這(zhè)裏我們使用golang:alpine版本。

這(zhè)是一(yī)個(gè)相對較小的linux系統。linux中的很多工具都被切斷了(le)。包管理(lǐ)工具使用apk。你可以拉這(zhè)個(gè)圖像Docker玩(wán)玩(wán)。默認外殼是sh。執行命令docker pull-t-I Golang : Alpine/bin/sh進入命令行。輸入後執行env查看環境變量,因為(wèi)其環境變量GOPATH對後續環境部署很有用,可以看到環境變量GOPATH的默認值是/go

2. 映射代碼文件并安裝

使用ADD src /go/src将主機scr文件映射到/go/src目錄。為(wèi)什(shén)麽一(yī)定是這(zhè)個(gè)/go/src目錄?沒錯,就(jiù)是上(shàng)面的GOPATH環境變量的路(lù)徑,因為(wèi)我們需要執行go install命令來(lái)稍後安裝,否則,我們需要重置GOPATH來(lái)安裝編譯後的二進制文件。

此時(shí),在需要注意的是:本地主機的src目錄中的文件組織必須嚴格遵循将要安裝時(shí)生(shēng)成的包的文件結構。test是程序的主程序,glog是使用的開源日志庫。整個(gè)文件結構如(rú)下(xià)。因為(wèi)main.go在導入包時(shí)使用了(le)“github.com/golang/glog'”路(lù)徑,所以有必要給它一(yī)個(gè)合理(lǐ)的路(lù)徑。

Dockerfile

src

github.com

golang

glog

glog_file.go

glog.go

glog_test.go

LICENSE

README

test

main.go還有一(yī)個(gè)小提示,程序的日志庫使用了(le)第三方開源glog。當我們使用git對我們上(shàng)面的代碼進行版本管理(lǐ)的時(shí)候,我們不需要重複包含glog的代碼,直接添加一(yī)個(gè)引用就(jiù)可以了(le)。這(zhè)樣有很多好(hǎo)(hǎo)處。當庫中的代碼被修改時(shí),可以直接更新(xīn)到遠(yuǎn)程代碼倉庫,克隆時(shí)可以自動導入庫,也(yě)就(jiù)是說(shuō)具體(tǐ)的代碼會被本地拉出來(lái)。

Glog可以通過命令生(shēng)成:gi子(zǐ)模式添加https://github.com/golang/glog.git src/github.com/golang/glog。注意:的git remoule命令中引用的位置是src/github.com/golang而不是src/direct,因為(wèi)執行這(zhè)個(gè)命令後,本地代碼倉庫會把glog克隆為(wèi)代碼倉庫,下(xià)拉它的代碼,隻把glog創建為(wèi)目錄,所以之前的一(yī)些(xiē)父目錄需要自己創建。

有關(guān)命令的更多信息,請參見Git。

Go install可以在組織好(hǎo)(hǎo)文件結構後進行,生(shēng)成的文件可以在$GOPATH/bin中執行,後面是基本的指定入口程序和參數。通過docker build -t='name '生(shēng)成圖像。

3.更進一(yī)步:提前編譯

上(shàng)面的方法是把代碼複制到基本鏡像裏面編譯。毫無疑問golang:alpine包含了(le)一(yī)系列的程序運行依賴,這(zhè)些(xiē)庫會在程序運行時(shí)動态加載。我們可以使用ldd命令來(lái)查看生(shēng)成的二進制文件的依賴關(guān)系:

Linux-vdso . so . 1=(0x 00007 ffc 5b 1 e 4000)

libpthread . so . 0=/lib/x86 _ 64-Linux-GNU/libpthread . so . 0(0x 00007 f 50 a1 f 13000)

libc . so . 6=/lib/x86 _ 64-Linux-GNU/libc . so . 6(0x 00007 f 50 a1 B4 a 000)

/lib64/ld-linux-x86-64.so.2

(0x00005611a4b0a000)

那麽問題來(lái)了(le)? 如(rú)果将這(zhè)些(xiē)依賴靜态編譯至可執行文件中那就(jiù)不需要在環境中保存這(zhè)些(xiē)多餘的信息了(le),就(jiù)可以創建一(yī)個(gè)更小的鏡像了(le)。幸運的是無論是golang的編譯機制還是docker的基礎鏡像都提供這(zhè)樣的實現(xiàn):

使用命令生(shēng)成靜态編譯的二進制文件:CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

此時(shí)用ldd查看生(shēng)成的可執行文件的依賴,可以看到顯示not a dynamic executable,這(zhè)裏我們禁用CGO使其生(shēng)成靜态二進制文件,同時(shí)設置系統為(wèi)linux。我們将基礎鏡像設置為(wèi) scratch,這(zhè)是一(yī)個(gè)很小的的鏡像。

重新(xīn)編寫的Dockerfile如(rú)下(xià):

FROMscratch
ADDmain/
ENTRYPOINT["/main"]
CMD["-logtostderr"]

執行docker build -t example-scratch .生(shēng)成鏡像,可以看到該鏡像的大小隻有8.27M大小,并且可以正常執行。

在實際情況中有時(shí)會将兩種情況結合使用,先在一(yī)個(gè)鏡像中構建,在另一(yī)個(gè)鏡像中執行。下(xià)面的Dockerfile摘自prometheus這(zhè)個(gè)第三方監控的演示案例的Dockerfile,可以看到它是首先在builder鏡像中下(xià)載對應的依賴并且編譯程序,最後在scratch基礎鏡像中執行程序。

#ThisDockerfilebuildsanimageforaclient_golangexample.
#
#Useas(fromtherootfortheclient_golangrepository):jingx
#dockerbuild-fexamples/$name/Dockerfile-tprometheus/golang-example-$name.
#Builderimage,wherewebuildtheexample.
FROMgolang:1.9.0ASbuilder
WORKDIR/go/src/github.com/prometheus/client_golang
COPY..
WORKDIR/go/src/github.com/prometheus/client_golang/prometheus
RUNgoget-d
WORKDIR/go/src/github.com/prometheus/client_golang/examples/simple
RUNCGO_ENABLED=0GOOS=linuxgobuild-a-tagsnetgo-ldflags'-w'
#Finalimage.
FROMscratch
LABELmaintainer"ThePrometheusAuthors<prometheus-developers@googlegroups.com>"
COPY--from=builder/go/src/github.com/prometheus/client_golang/examples/simple.
EXPOSE8080
ENTRYPOINT["/simple"]

感謝各位的閱讀!關(guān)于“怎麽為(wèi)Go程序創建一(yī)個(gè)最小的Docker Image”這(zhè)篇文章就(jiù)分(fēn)享到這(zhè)裏了(le),希望以上(shàng)内容可以對大家有一(yī)定的幫助,讓大家可以學到更多知識,如(rú)果覺得文章不錯,可以把它分(fēn)享出去讓更多的人(rén)看到吧(ba)!


/template/Home/Zkeys/PC/Static