基於gin的golang web開發:docker

Golang天生適合運行在docker容器中,這得益於:Golang的靜態編譯,當在編譯的時候關閉cgo的時候,可以完全不依賴系統環境。

一些基礎

測試容器時我們經常需要進入容器查看運行情況,以下命令啟動一個centos容器並進入bash交互環境。

docker run -it --rm centos bash

-it 組合參數-i: 以交互模式運行容器,-t: 為容器重新分配一個偽輸入終端。

–rm 在容器退出時就能夠自動清理容器。

alpine鏡像中沒有bash,啟動容器並進入終端的命令為

docker run -it --rm alpine sh

啟動一個golang編譯環境並進入bash

docker run -it -p 8081:8081 -v ./project:/app --env --env GO111MODULE=on --env GOPROXY=//goproxy.cn,direct --rm  --privileged golang:1.15 bash

-v ./project:/app 綁定本機項目的路徑映射到容器中/app

–env 設置環境變量,由於我們網絡環境的問題直接使用golang容器會很慢所以設置了GOPROXY=//goproxy.cn,direct。

–privileged 容器內的root擁有真正的root權限,否則容器內root只是外部的一個普通用戶。

-p 8081:8001 將本機的8081端口映射到容器的8001端口

docker打包項目

為了方便演示docker,我們準備一個簡單Gin項目。要注意r.Run不能綁定127.0.0.1。

func main() {
	r := gin.Default()

	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	r.Run("0.0.0.0:9999")
}

啟動golang容器,在容器中嘗試編譯並運行程序。

docker run -it -p 9999:9999 -v ./project:/app --env --env GO111MODULE=on --env GOPROXY=//goproxy.cn,direct --rm  --privileged golang:1.15 bash

Alpine和其他通用Linux發行版對於Golang編譯出來的可執行文件要求有所不同,Alpine要求可執行文件必須是靜態鏈接的可執行文件。所以在編譯Golang時需要添加 -tags netgo ,來生成靜態鏈接的可執行文件。

go build -tags netgo -o app .

把編譯出來的二進制文件和所有依賴項拷貝到發佈目錄

mkdir publish && cp app publish && \
    cp -r docs publish

golang鏡像的1.15版本有839M,再加上下載依賴編譯項目等各種文件的話最終鏡像可能會超過1G,大部分文件是在運行時不需要的。我們編寫Dockerfile的時候可以把編譯和運行兩個階段分開。編譯時使用golang鏡像,運行時使用alpine鏡像。alpine鏡像初始大小只有5M左右,非常適合作為基礎鏡像。最終Dockerfile如下

FROM golang:1.15 as builder

ENV GO111MODULE=on \
    GOPROXY=//goproxy.cn,direct

WORKDIR /app
COPY . .
RUN GOOS=linux GOARCH=amd64 go build -tags netgo -o app .

RUN mkdir publish && cp app publish && \
    cp -r docs publish


FROM alpine
WORKDIR /app
COPY --from=builder /app/publish .
ENV GIN_MODE=release \
    PORT=8081

EXPOSE 8081
ENTRYPOINT ["./app"]

構建docker鏡像,大功告成。

docker build -t test:0.1 .

文章出處:基於gin的golang web開發:docker

Tags: