【導(dǎo)讀】go 項(xiàng)目怎么讓 docker 鏡像體積減???本文做了詳細(xì)介紹。
1. 直接編譯得到運(yùn)行文件 22M
使用的項(xiàng)目源碼地址 (https://github.com/scoful/kingProject)
本地直接編譯打一個(gè)linux運(yùn)行包
setGOOS=linux
setGOARCH=amd64
gobuildmain.go
結(jié)果是22M
2. 不編譯直接運(yùn)行的鏡像 941M
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang最新鏡像構(gòu)建
FROMgolang
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR$GOPATH/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY.$GOPATH/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于不編譯打包,源代碼直接運(yùn)行)
ENTRYPOINT["go","run","main.go"]
編譯鏡像后查詢結(jié)果如下:
結(jié)果是941M,基本跟基礎(chǔ)鏡像golang的大小一致,而且因?yàn)闆](méi)有預(yù)先編譯,等到運(yùn)行的時(shí)候再編譯并拉取依賴包,run起來(lái)很慢
3. 編譯后的鏡像 1.14G
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang最新鏡像構(gòu)建
FROMgolang
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR$GOPATH/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY.$GOPATH/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯
RUNGOOS=linuxGOARCH=amd64gobuildmain.go
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
結(jié)果是1.14G,更大了,因?yàn)榧由狭司幾g過(guò)程中拉取的包,但是預(yù)先編譯,所以直接run,速度很快
4. 優(yōu)化:使用alpine版本的基礎(chǔ)鏡像 517M
優(yōu)化的方向:如果一個(gè)鏡像在https://hub.docker.com/里能搜到有alpine版本,盡量用alpine版本,相當(dāng)于是官方提供的最小化可用版本
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine版本鏡像構(gòu)建
FROMgolang:alpine
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR$GOPATH/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY.$GOPATH/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯
RUNGOOS=linuxGOARCH=amd64gobuildmain.go
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
結(jié)果是517M,比1.14G減少了650.36M,直接降了56%,而且run一樣很快
5. 再優(yōu)化:使用多級(jí)構(gòu)建的鏡像 28.4M
再優(yōu)化的方向:go項(xiàng)目其實(shí)只是在build的階段需要go環(huán)境,run的時(shí)候是不需要的,那build完后go環(huán)境用個(gè)alpine版本就行
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine鏡像構(gòu)建--編譯階段
FROMgolang:alpineASbuilder
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR/go/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY./go/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯,關(guān)閉CGO,防止編譯后的文件有動(dòng)態(tài)鏈接,而alpine鏡像里有些c庫(kù)沒(méi)有,直接沒(méi)有文件的錯(cuò)誤
RUNGOOS=linuxGOARCH=amd64CGO_ENABLED=0gobuildmain.go
#使用alpine這個(gè)輕量級(jí)鏡像為基礎(chǔ)鏡像--運(yùn)行階段
FROMalpineASrunner
#全局工作目錄
WORKDIR/go/kingProject
#復(fù)制編譯階段編譯出來(lái)的運(yùn)行文件到目標(biāo)目錄
COPY--from=builder/go/kingProject/main.
#復(fù)制編譯階段里的config文件夾到目標(biāo)目錄
COPY--from=builder/go/kingProject/config./config
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
結(jié)果是28.4M,比517M減少了488.6M,再降95%,那個(gè)533M是第一級(jí)構(gòu)建生成的
6. 再再優(yōu)化:使用多級(jí)構(gòu)建+scratch基礎(chǔ)鏡像 22.8M
再再優(yōu)化的方向:再極端一點(diǎn),第二級(jí)構(gòu)建的時(shí)候用個(gè)空鏡像來(lái)當(dāng)基礎(chǔ)鏡像
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine鏡像構(gòu)建--編譯階段
FROMgolang:alpineASbuilder
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR/go/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY./go/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯,關(guān)閉CGO,防止編譯后的文件有動(dòng)態(tài)鏈接,而alpine鏡像里有些c庫(kù)沒(méi)有,直接沒(méi)有文件的錯(cuò)誤
RUNGOOS=linuxGOARCH=amd64CGO_ENABLED=0gobuildmain.go
#使用scratch這個(gè)空鏡像為基礎(chǔ)鏡像--運(yùn)行階段
FROMscratchASrunner
#全局工作目錄
WORKDIR/go/kingProject
#復(fù)制編譯階段編譯出來(lái)的運(yùn)行文件到目標(biāo)目錄
COPY--from=builder/go/kingProject/main.
#復(fù)制編譯階段里的config文件夾到目標(biāo)目錄
COPY--from=builder/go/kingProject/config./config
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
結(jié)果是22.8M,已經(jīng)約等于不用鏡像直接編譯出的可執(zhí)行文件大小了,比28.4M減少了5.6M,再降20%,但用scratch當(dāng)基礎(chǔ)鏡像的壞處是沒(méi)法exec進(jìn)入容器內(nèi)部,因?yàn)檎娴木褪强甄R像,啥都沒(méi)有,啥都不支持
7. 再再再優(yōu)化:go編譯命令去掉冗余輸出 16.3M
再再再優(yōu)化的方向:再再極端一點(diǎn),go編譯的時(shí)候,加上參數(shù)-ldflags="-w -s"
,直接去掉一些冗余輸出內(nèi)容
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine鏡像構(gòu)建--編譯階段
FROMgolang:alpineASbuilder
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR/go/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY./go/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯,關(guān)閉CGO,防止編譯后的文件有動(dòng)態(tài)鏈接,而alpine鏡像里有些c庫(kù)沒(méi)有,直接沒(méi)有文件的錯(cuò)誤
RUNGOOS=linuxGOARCH=amd64CGO_ENABLED=0gobuild-ldflags="-w-s"main.go
#使用scratch這個(gè)空鏡像為基礎(chǔ)鏡像--運(yùn)行階段
FROMscratchASrunner
#全局工作目錄
WORKDIR/go/kingProject
#復(fù)制編譯階段編譯出來(lái)的運(yùn)行文件到目標(biāo)目錄
COPY--from=builder/go/kingProject/main.
#復(fù)制編譯階段里的config文件夾到目標(biāo)目錄
COPY--from=builder/go/kingProject/config./config
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
結(jié)果是16.3M,看似比不用鏡像直接編譯出的可執(zhí)行文件還小,那是因?yàn)橹苯泳幾g沒(méi)有加上這個(gè)參數(shù),如果加上大小還是差不多的,比22.8M減少了6.5M,再降29%,好了,降無(wú)可降了,用1.14G來(lái)對(duì)比的話,減少了1.12G,足足降了99%,鵝妹子嚶!
8. 最終版:順便解決時(shí)區(qū)問(wèn)題 16.3M
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine鏡像構(gòu)建--編譯階段
FROMgolang:alpineASbuilder
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR/go/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY./go/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯,關(guān)閉CGO,防止編譯后的文件有動(dòng)態(tài)鏈接,而alpine鏡像里有些c庫(kù)沒(méi)有,直接沒(méi)有文件的錯(cuò)誤
RUNGOOS=linuxGOARCH=amd64CGO_ENABLED=0gobuild-ldflags="-w-s"main.go
RUNecho"https://mirrors.aliyun.com/alpine/v3.8/main/">/etc/apk/repositories
&&echo"https://mirrors.aliyun.com/alpine/v3.8/community/">>/etc/apk/repositories
&&apkadd--no-cachetzdata
&&cp/usr/share/zoneinfo/Asia/Shanghai/etc/localtime
&&echoAsia/Shanghai>/etc/timezone
&&apkdeltzdata
#使用scratch這個(gè)空鏡像為基礎(chǔ)鏡像--運(yùn)行階段
FROMscratchASrunner
#全局工作目錄
WORKDIR/go/kingProject
#復(fù)制編譯階段編譯出來(lái)的運(yùn)行文件到目標(biāo)目錄
COPY--from=builder/go/kingProject/main.
#復(fù)制編譯階段里的config文件夾到目標(biāo)目錄
COPY--from=builder/go/kingProject/config./config
#復(fù)制編譯階段里的時(shí)區(qū)文件到目標(biāo)目錄
COPY--from=builder/etc/localtime/etc/localtime
COPY--from=builder/etc/timezone/etc/timezone
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
9. 最最推薦使用版:多級(jí)+alpine 21.9M
綜上所述,scratch鏡像有它的缺陷,是一個(gè)真的空鏡像,不支持很多命令,比如cp,sh等,如果要進(jìn)入容器內(nèi)部查東西,都進(jìn)不去,不適合真實(shí)情況,所以還是推薦alpine鏡像,很小5M多,可以接受。
Dockerfile文件內(nèi)容
#基礎(chǔ)鏡像,基于golang的alpine鏡像構(gòu)建--編譯階段
FROMgolang:alpineASbuilder
#作者
MAINTAINERscoful
#全局工作目錄
WORKDIR/go/kingProject
#把運(yùn)行Dockerfile文件的當(dāng)前目錄所有文件復(fù)制到目標(biāo)目錄
COPY./go/kingProject
#環(huán)境變量
#用于代理下載go項(xiàng)目依賴的包
ENVGOPROXYhttps://goproxy.cn,direct
#編譯,關(guān)閉CGO,防止編譯后的文件有動(dòng)態(tài)鏈接,而alpine鏡像里有些c庫(kù)沒(méi)有,直接沒(méi)有文件的錯(cuò)誤
RUNGOOS=linuxGOARCH=amd64CGO_ENABLED=0gobuild-ldflags="-w-s"main.go
#使用alpine這個(gè)輕量級(jí)鏡像為基礎(chǔ)鏡像--運(yùn)行階段
FROMalpineASrunner
#全局工作目錄
WORKDIR/go/kingProject
#復(fù)制編譯階段編譯出來(lái)的運(yùn)行文件到目標(biāo)目錄
COPY--from=builder/go/kingProject/main.
#復(fù)制編譯階段里的config文件夾到目標(biāo)目錄
COPY--from=builder/go/kingProject/config./config
#將時(shí)區(qū)設(shè)置為東八區(qū)
RUNecho"https://mirrors.aliyun.com/alpine/v3.8/main/">/etc/apk/repositories
&&echo"https://mirrors.aliyun.com/alpine/v3.8/community/">>/etc/apk/repositories
&&apkadd--no-cachetzdata
&&cp/usr/share/zoneinfo/Asia/Shanghai/etc/localtime
&&echoAsia/Shanghai>/etc/timezone
&&apkdeltzdata
#需暴露的端口
EXPOSE8888
#可外掛的目錄
VOLUME["/go/kingProject/config","/go/kingProject/log"]
#dockerrun命令觸發(fā)的真實(shí)命令(相當(dāng)于直接運(yùn)行編譯后的可運(yùn)行文件)
ENTRYPOINT["./main"]
over,Enjoy?。?!
原文標(biāo)題:給 go 項(xiàng)目打最小 docker 鏡像,足足降低 99%
文章出處:【微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
編譯
+關(guān)注
關(guān)注
0文章
657瀏覽量
32852 -
鏡像
+關(guān)注
關(guān)注
0文章
164瀏覽量
10707 -
Docker
+關(guān)注
關(guān)注
0文章
457瀏覽量
11846
原文標(biāo)題:給 go 項(xiàng)目打最小 docker 鏡像,足足降低 99%
文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛(ài)好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論