將 go 代碼打包成 docker 鏡像
概述
在本教程中,你將生成一個容器映像。該映像包括運行應用程序所需的一切:編譯的應用程序二進制文件、運行時、庫以及應用程序所需的所有其他資源。
前置條件
若要完成本教程,需要滿足以下條件:
-
golang 1.19+
-
本地安裝了 docker
-
Git 客戶端
程序
該應用程序提供兩個 HTTP endpoint:
-
/ 返回符號 < 3
-
/health 返回 {"Status" : "OK"}
應用程序偵聽由環境變量 PORT 定義的 TCP 端口。缺省值爲 8080
該應用程序的完整源代碼位於 GitHub 上:github.com/docker/docker-gs-ping。我們鼓勵您 fork 它並隨心所欲地嘗試它。
要繼續,請將應用程序存儲庫克隆到本地計算機:
git clone https://github.com/docker/docker-gs-ping
如果您熟悉 Go,該應用程序 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("/health", func(c echo.Context) error {
return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
})
httpPort := os.Getenv("PORT")
if httpPort == "" {
httpPort = "8080"
}
e.Logger.Fatal(e.Start(":" + httpPort))
}
// Simple implementation of an integer minimum
// Adapted from: https://gobyexample.com/testing-and-benchmarking
func IntMin(a, b int) int {
if a < b {
return a
}
return b
}
冒煙測試應用程序
啓動應用程序並確保它正在運行。打開終端並導航到將項目存儲庫克隆到的目錄。從現在開始,本指南將此目錄稱爲項目目錄
go run main.go
這應該將服務器編譯並啓動爲前臺應用程序,輸出橫幅,如下圖所示。
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.10.2
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⨠http server started on [::]:8080
通過訪問 上的 http://localhost:8080 應用程序來運行快速冒煙測試。您可以使用自己喜歡的 Web 瀏覽器,甚至可以在終端中使用 curl 命令:
curl http://localhost:8080/
Hello, Docker! <3
現在,您可以將其容器化了。
爲應用程序創建 Dockerfile
告訴 Docker 要爲應用程序使用哪個基礎映像:
# syntax=docker/dockerfile:1
FROM golang:1.19
Docker 鏡像可以從其他鏡像繼承。因此,您可以使用已經具有所有必要工具和庫的官方 Go 映像來編譯和運行 Go 應用程序,而不是從頭開始創建自己的基礎映像。
現在,您已經爲即將推出的容器映像定義了基礎映像,可以開始在它之上進行構建
若要在運行其餘命令時簡化操作,請在要生成的映像中創建一個目錄。這也指示 Docker 使用此目錄作爲所有後續命令的默認目標。這樣你就不必在 中鍵入完整的文件路徑 Dockerfile ,相對路徑將基於此目錄
WORKDIR /app
通常,一旦你下載了一個用 Go 編寫的項目,你要做的第一件事就是安裝編譯它所需的模塊。請注意,基礎映像已包含工具鏈,但源代碼尚未包含在其中。
因此,在運行映像 go mod download 之前,需要將 go.mod 和 go.sum 文件複製到其中。使用命令 COPY 執行此操作。
在最簡單的形式中,該 COPY 命令採用兩個參數。第一個參數告訴 Docker 要將哪些文件複製到映像中。最後一個參數告訴 Docker 您希望將該文件複製到何處。
將 go.mod and go.sum 文件複製到您的項目目錄中,由於您使用了 WORKDIR ,該目錄是映像中的當前目錄 /app ( ./ )。與一些現代 shell 似乎對尾部斜槓的使用漠不關心 ( ),並且可以弄清楚用戶的意思(大多數時候 / ),Docker COPY 的命令在解釋尾部斜槓時非常敏感。
COPY go.mod go.sum ./
現在,您已經在要構建的 Docker 映像中擁有模塊文件,也可以使用該命令在該命令中運行該 RUN 命令 go mod download 。這與在計算機上本地運行 go 的工作方式完全相同,但這次這些 Go 模塊將安裝到映像中的目錄中。
RUN go mod download
接下來需要做的是將源代碼複製到映像中。您將像之前使用模塊文件一樣使用該 COPY 命令。
COPY *.go ./
此 COPY 命令使用通配符將主機上當前目錄(所在的 Dockerfile 目錄)中擴展 .go 名的所有文件複製到映像內的當前目錄中。
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
該命令將代碼編譯成一個二進制文件,該二進制文件被命名 docker-gs-ping 並位於您正在構建的映像的文件系統的根目錄中。您可以將二進制文件放入該映像中您想要的任何其他位置。
現在,剩下要做的就是告訴 Docker 在使用鏡像啓動容器時要運行什麼命令。您可以使用以下 CMD 命令執行此操作:
CMD ["/docker-gs-ping"]
以下是完整的 Dockerfile :
# syntax=docker/dockerfile:1
FROM golang:1.19
# Set destination for COPY
WORKDIR /app
# Download Go modules
COPY go.mod go.sum ./
RUN go mod download
# Copy the source code. Note the slash at the end, as explained in
# https://docs.docker.com/engine/reference/builder/#copy
COPY *.go ./
# Build
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
# Optional:
# To bind to a TCP port, runtime parameters must be supplied to the docker command.
# But we can document in the Dockerfile what ports
# the application is going to listen on by default.
# https://docs.docker.com/engine/reference/builder/#expose
EXPOSE 8080
# Run
CMD ["/docker-gs-ping"]
生成映像
現在,您已經創建了 Dockerfile ,讓我們來生成鏡像。 build context 是位於指定路徑或 URL 中的一組文件。Docker 構建過程可以訪問 context 中的任何文件, 在這裏我們用 . 來標識當前 context 爲同級目錄。
build 命令可以選擇採用標誌 --tag 。此標誌用於使用字符串值標記圖像,如果不傳遞 , --tag Docker 將用作 latest 默認值
構建您的第一個 Docker 映像。
docker build --tag docker-gs-ping .
查看本地鏡像
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-gs-ping latest 7f153fbcc0a8 2 minutes ago 1.11GB
...
給鏡像打 tag
鏡像名稱由以斜槓分隔的名稱組件組成。名稱組件可以包含小寫字母、數字和分隔符。分隔符定義爲句點、一個或兩個下劃線或一個或多個破折號。名稱組件不能以分隔符開頭或結尾。
您可以爲圖像設置多個 tag,事實上,大多數圖像都有多個標籤。爲您構建的鏡像打第二個 tag 。使用 docker image tag (或 docker tag 速記)命令爲鏡像創建新標籤。此命令採用兩個參數; 第一個參數是源圖像,第二個參數是要創建的新標記。以下命令爲您構建的 docker-gs-ping:latest 創建一個新 docker-gs-ping:v1.0 標籤:
docker image tag docker-gs-ping:latest docker-gs-ping:v1.0
現在再次運行查看本地鏡像命令,你會看到 tag = v1.0 的鏡像。
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-gs-ping latest 7f153fbcc0a8 6 minutes ago 1.11GB
docker-gs-ping v1.0 7f153fbcc0a8 6 minutes ago 1.11GB
...
我是南哥,日常分享高質量文章、架構設計、前沿資訊,加微信拉粉絲交流羣,和大家交流!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/i5fltG0lHpMWN45FnzudOg