如何在開發和生產環境中使用 Docker 容器化 Golang 應用

語言: CN / TW / HK

Photo by Ian Taylor on  Unsplash .

你是否想寫一個使用 Docker 容器化的 Golang 應用程式?本文的目的就是幫助你快速將你的 Golang 應用程式容器化,以用於 開發 (帶熱載入)和 生產 目的。

開始之前

請先安裝 Docker Desktop ,然後再繼續。安裝後,啟動桌面應用程式,如果它執行成功,你就可以開始了。

此外,我假設你有一個 $GOPATH 目錄,你可以在裡面放置你正在處理的 Golang 原始碼。比如我的是: ~/go/src/github.com/bartmika

… 但我不熟悉 Docker 怎麼辦?

別擔心!Docker 是一個成熟的工具集,它已經存在了足夠長的時間,可以提供大量優秀的教學資源來幫助你學習。我推薦以下內容,因為它對我幫助很大:

檢視我寫的另外一篇文章,可以幫助你學習基礎知識

  • 絕對是面向 Golang 程式設計初學者的 Docker 學習資源

將Golang 和 Docker 用於熱載入的開發環境

在本節中,你將學習如何在你的機器上設定你的 Golang 應用程式進行本地開發。開發容器的目的是儲存所有依賴項(例如:第三方包,如 GORM )、基礎設施(例如:資料庫、記憶體快取等)以及幫助和提升你開發的程式碼。

  • 建立我們應用程式的倉庫

   mkdir mullberry-backend
cd mullberry-backend
go mod init github.com/bartmika/mullberry-backen
  • 每次你想要增加依賴,你都可以關閉當前執行的容器並安裝依賴項。按照如下方式安裝我們的依賴項:

   go get github.com/labstack/echo/v4
go get github.com/labstack/echo/v4/[email protected]
  • 等等,你需要在本地安裝 Golang 嗎?那麼容器的意義何在?這個 Stackoverflow  使用者在討論為開發目的設定  Dockerfile  時解釋得最好:

當你想要把應用打包到容器中以準備部署時, Dockerfile 是非常棒的。對於希望將原始碼放在容器外部的開發和希望正在執行的容器對原始碼的改變作出反應的開發來說,就不是很合適了。

所以從本質上講,如果你對這個限制沒意見,那就繼續吧!

  • 在你的專案的根目錄建立  main.go  檔案,並複製貼上下面程式碼:
     package main

import (
"net/http"
"os"

"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)

func main() {

e := echo.New()

e.Use(middleware.Logger())
e.Use(middleware.Recover())

e.GET("/", func(c echo.Context) error {
return c.HTML(http.StatusOK, "Hello, Docker! <3")
})

e.GET("/ping", func(c echo.Context) error {
return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
})

httpPort := os.Getenv("HTTP_PORT")
if httpPort == "" {
httpPort = "8080"
}

e.Logger.Fatal(e.Start(":" + httpPort))
}

注意,上面的程式碼是從 Docker 文件構建你的 Go 映象 複製而來。

  • 在建立任何與 docker 相關的內容之前,請建立一個 .dockerignore 檔案 並複製並貼上以下內容:
       bin
.dockerignore
Dockerfile
docker-compose.yml
dev.Dockerfile
dev.docker-compose.yml
.env

什麼是 .dockerignore 檔案?本質上,它類似於  .gitignore 其中某些檔案/資料夾不會儲存到 docker 容器和映象中。

  • 建立 dev.Dockerfile 檔案並將以下內容複製並貼上到其中。

      FROM golang:1.18

# Copy application data into image
COPY . /go/src/bartmika/mullberry-backend
WORKDIR /go/src/bartmika/mullberry-backend

COPY go.mod ./
COPY go.sum ./
RUN go mod download

# Copy only `.go` files, if you want all files to be copied then replace `with `COPY . .` for the code below.
COPY *.go .

# Install our third-party application for hot-reloading capability.
RUN ["go", "get", "github.com/githubnemo/CompileDaemon"]
RUN ["go", "install", "github.com/githubnemo/CompileDaemon"]

ENTRYPOINT CompileDaemon -polling -log-prefix=false -build="go build ." -command="./mullberry-backend" -directory="./"
  如果你閱讀上面的註釋,你會注意到 `CompileDaemon` (http://github.com/githubnemo/CompileDaemon) 的用法。那是什麼?本質上它是你的熱載入器!它在一個目錄中監視你的 .go 檔案,如果檔案發生變化,它會呼叫 `go build`。 例如,你在 `Atom` IDE 中開啟這個專案,修改 `main.go` 檔案並點選 _Save_,然後 [`CompileDaemon`](http://github.com/githubnemo/CompileDaemon) 將重建你容器中的 Go 應用程式,所以你可以看到最新的構建!
  • 建立我們的 dev.docker-compose.yml 檔案:

   version: '3.6'

services:
api:
container_name: mullberry-backend
image: mullberry-backend
ports:
- 8000:8080
volumes:
- ./:/go/src/bartmika/mullberry-backend
build:
dockerfile: dev.Dockerfile

等等,為什麼我對這些 Docker 檔名使用 dev. 字首?原因是因為我想區分用於 生產開發 目的的 Docker 檔案。

  • 在你的終端中,使用以下命令啟動開發環境:

   $ docker-compose -f dev.docker-compose.yml up
  • 確認我們可以訪問它。

    $ curl localhost:8000/
  • 你將在你的終端中看到以下輸出:

Hello, Docker! <3   

如果你看到這個,恭喜你已經準備好開始開發了!如果你想了解更多資訊,請隨時通過他們的 Docker 文件檢視構建你的 Go 映像 一文。

將 Golang 和 Docker 用於生產環境

本節的目的是讓你的 Golang 應用程式容器化並準備好在生產環境中執行。

選項 1:單階段

最簡單的設定就是單階段構建。這樣構建的問題就是你的 Docker 映象將非常大。首先,在你的專案根資料夾中建立一個 Dockerfile 並將以下內容複製並貼上到其中:

FROM golang:1.18
# Copy application data into image
COPY . /go/src/bartmika/mullberry-backend
WORKDIR /go/src/bartmika/mullberry-backend
COPY go.mod ./
COPY go.sum ./
RUN go mod download
# Copy only `.go` files, if you want all files to be copied then replace `with `COPY . .` for the code below.
COPY *.go .
# Build our application.
RUN go build -o ./bin/mullberry-backend
EXPOSE 8080
# Run the application.
CMD ["./bin/mullberry-backend"]

然後執行  up  命令,你將會看到它工作:

$ docker-compose up

選項 2:多階段

一個更復雜的設定被稱為_多階段構建_可以節省磁碟空間。主要思路是你在一個容器中構建你的 Golang 應用程式,然後將它移動到另一個更小的容器中,從而丟棄了磁碟空間沉重的容器。

如果你想嘗試一下,請在專案根資料夾中建立一個 Dockerfile ,然後將以下內容複製並貼上到其中:

##
## Build
##
FROM golang:1.18-alpine as dev-env

# Copy application data into image
COPY . /go/src/bartmika/mullberry-backend
WORKDIR /go/src/bartmika/mullberry-backend

COPY go.mod ./
COPY go.sum ./
RUN go mod download

# Copy only `.go` files, if you want all files to be copied then replace `with `COPY . .` for the code below.
COPY *.go .

# Build our application.
# RUN go build -o /go/src/bartmika/mullberry-backend/bin/mullberry-backend
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags "all=-N -l" -o /server

##
## Deploy
##
FROM alpine:latest
RUN mkdir /data

COPY --from=dev-env /server ./
CMD ["./server"]

然後執行  up  命令,你將會看到它工作:

$ docker-compose up

-------

相關連結:

Ian Taylor http://unsplash.com/@carrier_lost

Unsplash http://unsplash.com/photos/jOqJbvo1P9g

Docker Desktop http://www.docker.com/get-started/

Docker 學習資源:

http://bartlomiejmika.com/post/2021/docker-learning-resources-for-absolute-

beginners-programming-with-golang/

GORM http://gorm.io/index.html

Stackoverflow:

http://stackoverflow.com/a/71297861

Go 映象

http://docs.docker.com/language/golang/build-images/

Go 映像

http://docs.docker.com/language/golang/build-images/

-------

原文地址:

http://bartlomiejmika.com/posts/2022/how-to-containerize-a-golang-app-with-docker-for-development-and-production/

原文作者:

Bartlomiej Mika

本文永久連結:

http://github.com/gocn/translator/blob/master/2022/w39_How_to_Containerize_a_Golang_App_With_Docker_for_Development_and_Production.md

譯者 :朱亞光

校對 :劉思家

2022 GopherChina大會報名火熱進行中!

掃描下方二維碼即可報名參與

大會合作、現場招聘及企業購票等事宜請聯絡 微信:18516100522

戳這裡 GO!