上期的文章:Kubernetes入門實踐--部署運行Go項目發佈後,有網友留言說我文章裏演示的鏡像是把項目文件和Go都打包到了鏡像裏,這樣鏡像的佔用空間會比較大。linux
Go
開發的程序在編譯成二進制文件後是能夠在沒有安裝Go
環境的系統裏執行的,若是隻把編譯完的二進制文件直接放到鏡像裏就能節省不少鏡像空間了。我給的回覆是文章的側重點是Kubernetes
的實踐因此鏡像方面就沒有佔太多篇幅。golang
確實真實線上項目的應用鏡像通常都不像以前文章裏講那樣構建,由於生產項目各方面要求更嚴格些。鏡像構建的過程通常都是先用Docker
容器把項目編譯成二進制文件,而後把編譯好的文件拷貝到一個新的容器鏡像裏,新鏡像裏通常只包含Linux
系統運行須要的最基本的文件,不須要有Go
環境,所以能減小不少佔用空間。整個這個過程都發生在鏡像構建的過程當中,這樣就能保證多環境的一致性,上面這個構建Docker
鏡像的方式叫作多階段構建(multi stage build
)。docker
多階段構建是17.05
版本纔有的功能,因此使用前要先肯定下使用的Docker Engine
的版本。bash
下面就來介紹一下怎麼使用Docker
的多階段構建制做Go
應用的鏡像。app
以前文章裏鏡像的Dockerfile
長這樣:工具
FROM golang:1.14-alpine
RUN mkdir /app COPY . /app WORKDIR /app RUN go build -o main . CMD ["/app/main"] 複製代碼
咱們使用用多階段構建的方式構建鏡像後,Dockerfile
會變成相似下面這樣:ui
FROM golang:alpine AS build
RUN mkdir /app COPY . /app WORKDIR /app RUN CGO_ENABLED=0 GOOS=linux go build -o myapp
###
FROM scratch as final
COPY --from=build /app/myapp . CMD ["/myapp"] 複製代碼
Go
項目應用的Dockerfile
一般大概相似這樣,可是每一個項目的細節可能有所不一樣。FROM golang:alpine
指定了開始階段的基礎映像(其中包含Go工具和庫,用於構建程序),AS build
是給這個階段取名爲build
。spa
golang:alpine
指定了Go
基礎映像的alpine
版本, alpine
是專門爲容器設計的小型Linux
發行版。這個Dockerfile
中使用了兩次FROM
指令,第二條FROM scratch
行,它告訴Docker
從一個全新的,徹底空的容器鏡像從新開始,而後將上個階段編譯好的程序複製到其中。這個纔是咱們隨後將用於運行的Go
應用程序的容器鏡像。設計
scratch
鏡像是Docker
項目預約義的最小的鏡像。 Docker
用於Go
程序的多階段構建很常見,使用scratch
鏡像能夠節省大量空間,由於咱們實際上不須要Go
工具或其餘任何東西來運行咱們的編譯好的程序,這可能也是Go
在容器時代的一個優點吧。code
使用scratch
鏡像製做的Go
應用鏡像在運行時會有一個不識別時區的問題,這個也是咱們最近項目往Kubernetes
上遷移時遇到的第一個問題,不過還好通過Google
和查看Go
加載時區的源碼找到了解決方法,具體怎麼解決的下期的文章再告訴你們。