使用 Docker Multi-Stage 編譯 Go 程序最佳姿勢(shì)
作者:AppleBoy
鏈接:http://suo.im/5KL8v2
本文通過 Go 語言的 Hello World 來介紹基于 Docker 的 Single build 及 Multiple build。
▍Single build
下面是 Go 語言 Hello World 代碼:
package?main
import?"fmt"
func?main()?{
????fmt.Println("Hello?World!")
}
接著用?alpine?的 Go 語言 Image 來編譯出可執(zhí)行文件。
FROM?golang:alpine
WORKDIR?/app
ADD?.?/app
RUN?cd?/app?&&?go?build?-o?app
ENTRYPOINT?./app
接著執(zhí)行如下編譯指令:
$?docker?build?-t?appleboy/go-app?.
$?docker?run?--rm?appleboy/go-app
最后檢查看看編譯出來的 Image 大小,使用docker images | grep go-app,會(huì)發(fā)現(xiàn)大小為?258 MB
▍Multiple build
Multiple build 則是可以在Dockerfile使用多個(gè)不同的 Image 來源,請(qǐng)看看底下例子:
#?build?stage
FROM?golang:alpine?AS?build-env
ADD?.?/src
RUN?cd?/src?&&?go?build?-o?app
#?final?stage
FROM?alpine
WORKDIR?/app
COPY?--from=build-env?/src/app?/app/
ENTRYPOINT?./app
從上面可以看到透過AS和--from互相溝通,以前需要寫兩個(gè) Dockerfile,現(xiàn)在只要一個(gè)就可以搞定。
$?docker?build?-t?appleboy/go-app?.
$?docker?run?--rm?appleboy/go-app
會(huì)發(fā)現(xiàn)最后大小為?6.35 MB,比上面是不是小了很多。
▍最小 Image
6.35 MB?是最小的 Image 了嗎?一個(gè)簡(jiǎn)單的 Hello World 可執(zhí)行文件,用 Docker 包起來竟然要 6.35,其實(shí)不用這么大,我們可以透過 Dokcer 所提供的最小 Image:scratch,將二進(jìn)制文件直接扔進(jìn)去即可,在編譯可執(zhí)行文件時(shí)需加入特定參數(shù)才可以:
$?CGO_ENABLED=0?GOOS=linux?GOARCH=amd64?go?build?-o?app
在通過 Docker 包起來:
FROM?centurylink/ca-certs
ADD?app?/
ENTRYPOINT?["/app"]
編譯出來大小為:1.81MB,相信這是最小的 Image 了。
注:centurylink/ca-certs 是一個(gè)基于 Docker 的基礎(chǔ)鏡像,它基于?scratch?鏡像構(gòu)建,并為所有標(biāo)準(zhǔn)證書頒發(fā)機(jī)構(gòu)添加了根證書。
完整的 Dockerfile:
#?build?stage
FROM?golang:alpine?AS?build-env
ADD?.?/src
RUN?cd?/src?&&?CGO_ENABLED=0?GOOS=linux?GOARCH=amd64?go?build?-o?app
#?final?stage
FROM?centurylink/ca-certs
COPY?--from=build-env?/src/app?/
ENTRYPOINT?["/app"]
▍總結(jié)
Multiple build 非常方便,這樣就可以將多個(gè)步驟全部合并在一個(gè) Dockerfile 處理掉,像是底下例子:
from?debian?as?build-essential
arg?APT_MIRROR
run?apt-get?update
run?apt-get?install?-y?make?gcc
workdir?/src
from?build-essential?as?foo
copy?src1?.
run?make
from?build-essential?as?bar
copy?src2?.
run?make
from?alpine
copy?--from=foo?bin1?.
copy?--from=bar?bin2?.
cmd?...
用一個(gè) Dockerfile 產(chǎn)生多個(gè)可執(zhí)行文件,最后再用 alpine 打包成 Image。
- END -
精彩文章推薦:
從網(wǎng)管到架構(gòu)師再到微創(chuàng)業(yè),我這9年的成長(zhǎng)感悟
12年老司機(jī)總結(jié)的 5 條面試忠告,終身受用
一篇漫畫帶你了解 Linux 內(nèi)核長(zhǎng)啥樣!
SSH只能用于遠(yuǎn)程Linux主機(jī)?那說明你見識(shí)太小了!
10 個(gè)Linux Awk文本處理經(jīng)典案例
部署一套完整的Kubernetes高可用集群(二進(jìn)制)
點(diǎn)亮,服務(wù)器三年不宕機(jī)

