輕松容器化 Golang 應(yīng)用程序
Golang 工程,尤其是當(dāng)您使用 Docker 運(yùn)行 Go 項(xiàng)目的可執(zhí)行文件時(shí)。我們可以從我們的項(xiàng)目中創(chuàng)建我們的鏡像,簡單地在您的本地計(jì)算機(jī)上運(yùn)行它,甚至可以通過從 harbour 中提取您的鏡像運(yùn)行它。# 要求
docker
Go 編程環(huán)境
倉庫: https://github.com/strictnerd/go-dockerfile
# 入門
首先,您需要使用systemctl start docker或啟動(dòng)您的 docker 守護(hù)進(jìn)程service docker start,如果需要必要權(quán)限請(qǐng)使用sudo。
然后我們將創(chuàng)建我們簡單的 go HTTP 代碼。
$?mkdir?go-dockerfile?&&?cd?go-dockerfile?
$?go?mod?init?myapp?
$?touch?server.go
server.go:
package?main
import?(
?"os"
?"github.com/gin-gonic/gin"
?"github.com/joho/godotenv"
)
func?init()?{
?godotenv.Load()
}
func?main()?{
?port?:=?os.Getenv("PORT")
?if?port?==?""?{
??port?=?"8080"
?}
?router?:=?gin.Default()
?router.GET("/",?func(c?*gin.Context)?{
??c.String(200,?"Hello?World")
?})
?router.GET("/env",?func(c?*gin.Context)?{
??c.String(200,?"Hello?%s",?os.Getenv("NAME"))
?})
?router.Run(":"?+?port)
}
我們將包含一個(gè)簡單的gin路由器和可選的.server.gogodotenv``/path 將返回“Hello World”,/envpath 將返回“Hello ${NAME}”。
# Dockerfile
有多種編寫方式Dockerfile,但我將使用不同的基礎(chǔ)圖像制作
3 個(gè)示例:golang docker、alpine、scratch。
?官方Dockerfile
FROM?golang:1.16-alpine
WORKDIR?/project/go-docker/
#?COPY?go.mod,?go.sum?and?download?the?dependencies
COPY?go.*?./
RUN?go?mod?download
#?COPY?All?things?inside?the?project?and?build
COPY?.?.
RUN?go?build?-o?/project/go-docker/build/myapp?.
EXPOSE?8080
ENTRYPOINT?[?"/project/go-docker/build/myapp"?]
在此Dockerfile,我們將其分為幾個(gè)部分:
FROM golang:1.16-alpine,我們將golang:1.16-alpine用作此 Docker 構(gòu)建的基礎(chǔ)鏡像。
WORKDIR, 將是我們命令的工作目錄/下一個(gè)命令的路徑。
COPY go.* ./,我們將從我們的項(xiàng)目復(fù)制go.mod&go.sum文件到工作目錄。
RUN go mod download , 從 go modules 下載項(xiàng)目依賴。
COPY . . ,將我們項(xiàng)目中的所有內(nèi)容復(fù)制到工作目錄中。
RUN go build -o /project/go-docker/build/myapp ., 在工作目錄中構(gòu)建我們的項(xiàng)目并將其project/go-docker/build/myapp作為二進(jìn)制文件輸出。
EXPOSE 8080,告訴 docker 我們的代碼將暴露端口8080。
ENTRYPOINT ["/project/go-docker/build/myapp"] ,當(dāng)我們運(yùn)行這個(gè)鏡像的容器時(shí),它將從我們的構(gòu)建可執(zhí)行文件開始執(zhí)行。
之后我們需要運(yùn)行這個(gè)命令:
docker?build?-f?Dockerfile?-t?test-go-docker:latest?.
-f flag 是我們的Dockerfile.
-t tag 是鏡像標(biāo)簽。
.命令是當(dāng)前文件夾下的Dockerfile.
嘗試運(yùn)行此命令docker images,例如:

?alpine
FROM?golang:1.16-alpine?as?builder
WORKDIR?/project/go-docker/
#?COPY?go.mod,?go.sum?and?download?the?dependencies
COPY?go.*?./
RUN?go?mod?download
#?COPY?All?things?inside?the?project?and?build
COPY?.?.
RUN?go?build?-o?/project/go-docker/build/myapp?.
FROM?alpine:latest
COPY?--from=builder?/project/go-docker/build/myapp?/project/go-docker/build/myapp
EXPOSE?8080
ENTRYPOINT?[?"/project/go-docker/build/myapp"?]
與golang 官方基礎(chǔ)鏡像的區(qū)別:
FROM golang:1.16-alpine as builder,我們將使用golang:1.16-alpine并標(biāo)記它,builder因?yàn)樯院髮⑹褂盟?/span>
FROM alpine:latest,我們用alpine作為基礎(chǔ)鏡像.
COPY --from=builder /project/go-docker/build/myapp /project/go-docker/build/myapp ,將構(gòu)建的二進(jìn)制文件復(fù)制到新的 alpine 鏡像中。
這個(gè)Dockerfile生成的鏡像比之前小得多。

?Scratch
FROM?golang:1.16-alpine?as?builder
WORKDIR?/project/go-docker/
#?COPY?go.mod,?go.sum?and?download?the?dependencies
COPY?go.*?./
RUN?go?mod?download
#?COPY?All?things?inside?the?project?and?build
COPY?.?.
RUN?go?build?-o?/project/go-docker/build/myapp?.
FROM?scratch
COPY?--from=builder?/project/go-docker/build/myapp?/project/go-docker/build/myapp
EXPOSE?8080
ENTRYPOINT?[?"/project/go-docker/build/myapp"?]
對(duì)于最后一個(gè) Dockerfile,我們只將alpine基礎(chǔ)鏡像更改為scratch. Scratch 是一個(gè)空鏡像,所以一旦容器運(yùn)行,我們就無法執(zhí)行到容器中,因?yàn)樗鼪]有 shell 命令。如下是輸出的 docker images。

運(yùn)行鏡像docker run -d -p 8080:8080 test-go-docker:latest,它將端口8080從容器轉(zhuǎn)發(fā)到物理節(jié)點(diǎn)8080端口并可以訪問http://localhost:8080.
# 結(jié)論
就我個(gè)人而言,我會(huì)選擇第二個(gè)Dockerfile。為什么?因?yàn)轶w積小而且它還有幾個(gè)命令和一個(gè)shell命令所以我們可以docker exec進(jìn)入容器并訪問它。如果我們使用scratch基礎(chǔ)鏡像,因?yàn)槲覀儫o法執(zhí)行它,所以將很難調(diào)試正在運(yùn)行的容器。
? ?

???
