上期的文章: Kubernetes入門實踐--部署運行Go項目 發佈後,有網友留言說我文章裏演示的鏡像是把項目文件和Go都打包到了鏡像裏,這樣鏡像的佔用空間會比較大。

Go 開發的程序在編譯成二進制文件後是可以在沒有安裝 Go 環境的系統裏執行的,如果只把編譯完的二進制文件直接放到鏡像裏就能節省很多鏡像空間了。我給的回覆是文章的側重點是 Kubernetes 的實踐所以鏡像方面就沒有佔太多篇幅。

確實線上項目的應用鏡像一般都不像之前文章裏講的那樣構建,因爲生產項目各方面要求更嚴格些。鏡像構建的過程一般都是先用 Docker 容器把項目編譯成二進制文件,然後把編譯好的文件拷貝到一個新的容器鏡像裏,新鏡像裏一般只包含 Linux 系統運行需要的最基本的文件,不需要有 Go 環境,因此能減少很多佔用空間。整個這個過程都發生在鏡像構建的過程中,這樣就能保證多環境的一致性,上面這個構建 Docker 鏡像的方式叫做多階段構建( multi stage build )。

多階段構建是 17.05 版本纔有的功能,所以使用前要先確定下使用的 Docker Engine 的版本。

Docker Engine版本

下面就來介紹一下怎麼使用 Docker 的多階段構建制作 Go 應用的鏡像。

之前文章 Kubernetes入門實踐--部署運行Go項目 裏鏡像的 Dockerfile 長這樣:

FROM golang:1.14-alpine
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN go build -o main .
CMD ["/app/main"]

我們使用多階段構建的方式構建鏡像後, Dockerfile 會變成類似下面這樣:

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

golang:alpine 指定了 Go 基礎映像的 alpine 版本, alpine 是專門爲容器設計的小型 Linux 發行版。這個 Dockerfile 中使用了兩次 FROM 指令,第二條 FROM scratch 行,它告訴 Docker 從一個全新的,完全空的容器鏡像重新開始,然後將上個階段編譯好的程序複製到其中。這個纔是我們隨後將用於運行的 Go 應用程序的容器鏡像。

scratch 鏡像是 Docker 項目預定義的最小的鏡像。使用 scratch 鏡像可以節省大量空間,因爲我們實際上不需要 Go 工具或其他任何東西來運行我們的編譯好的程序,這可能也是 Go 在容器時代的一個優勢吧。

使用 scratch 鏡像製作的 Go 應用鏡像在運行時會有一個不識別時區的問題。這個也是我們最近項目往 Kubernetes 上遷移時遇到的第一個問題,不過還好經過 Google 和查看 Go 加載系統時區的源碼我幫新來的運維小哥哥找到了解決方法,具體怎麼解決的下期的文章再告訴大家。

容器和虛擬機到底有啥區別?

Minikube-筆記本上的Kubernetes集羣

:heart:愛心三連

1.看到這裏了就點個在看支持下吧,你的 在看 是我創作的動力。

2.關注公衆號 網管叨bi叨「每週爲您分享原創技術文章」

3.特殊階段,帶好口罩,做好個人防護。

“在看轉發” 是最大的支持

相關文章