如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

你或許想在 Docker 中使用 Go,原因有:

  1. 如果你想在 Kubernetes 上運行,打包為鏡像是必須的(就像我一樣)
  2. 你不得不在同一臺機器上運行不同的 Go 版本
  3. 開發和生產都需要精確的、可複製的、可共享的和確定的環境
  4. 你需要快速和簡單的方式來構建和部署編譯好的二進制文件
  5. 你想快速開始(任何安裝了 Docker 的人都可以直接開始編寫代碼而不需要設置其他依賴或 GOPATH 環境變量)

恭喜你,你來對地方了。

我們將逐步構建一個基本的 Dockerfile,包括實時重載包管理,然後進行擴展,創建一個高度優化的生產版的鏡像,其大小縮減了 100 倍。如果你使用 CI/CD 系統,鏡像大小可能無關緊要,但是當 docker push 和 docker pull 時,一個精簡的鏡像肯定會有幫助。

如果你只想要最終的代碼,請看 GitHub

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

假設我們的應用叫 go-docker,下面是項目的結構。所有的源碼都在 src 目錄下,Dockerfile 跟它在同一級目錄。 main.go 定義了一個 web-app 並監聽 8080 端口。

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

最簡單的版本

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

我們使用 debian jessie 版本的 golang 鏡像,因為像 go get 這樣的命令需要安裝有 git 等工具。對於生產版本,我們會用更加輕量的版本,如 alpine。

構建並運行該鏡像:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

成功後可以通過 http://localhost:8080 來訪問。按下 Ctrl+C 可以中斷服務。

但這並沒有多大意義,因為每次修改代碼時,我們都必須構建和運行docker 鏡像。

一個更好的版本是將源代碼掛載到 docker 容器中,並使用容器內的 shell 來停止和啟動 go run。

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

這個命令會提供一個 shell,我們可以在裡面執行 go run src/main.go 以啟動服務。我們可以在宿主機上編輯 main.go 並重新運行該命令來查看變化,因為現在源代碼已經直接掛載到了容器中。

但是,如何管理包呢?

包管理和鏡像分層

Go 的包管理 仍處在實驗階段。有很多工具可以選擇,但是我最喜歡的是 Glide。我們將在容器中安裝 Glide 並使用它。

在 go-docker 項目中新建兩個文件 glide.yaml 和 glide.lock:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

按照下面所示修改 Dockerfile 並構建一個新的鏡像:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

如果你觀察比較細緻,你會發現 glide.yaml 和 glide.lock 是分開添加的(並沒有用 ADD . .),這樣會導致有單獨分離的層。將包管理分離為單獨的層,可以充分利用 Docker 層的緩存,並且只有當對應的文件發生變化才會導致重新編譯,比如:新增或刪除了一個包。因此,glide install 不會在每次修改了代碼之後都去執行。

讓我們進入容器的 shell 安裝一個包:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

Glide 會將所有包安裝到 vendor 目錄,該目錄可以被 gitignored 和 dockerignored。使用 glide.lock 來鎖定某個包的版本。要安裝(或重新安裝)glide.yaml 中提到的所有包,執行:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

現在 go-docker 目錄有所增長:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

實時重載

codegangsta/gin 是我最喜歡的實時重載工具。它簡直就是為 Go web 服務而生的。我們使用 go get 來安裝 gin:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

構建鏡像並運行 gin 以便當我們修改了 src 中的源代碼時可以自動重新編譯:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

注意到 web-server 需要一個 PORT 的環境變量來監聽,因為 gin 會隨機設置 PORT 變量並代理到該端口的連接。

現在,修改 src 目錄下的內容會觸發重新編譯,所有更新的內容可以實時在 http://localhost:8080 訪問到。

一旦開發完畢,我們可以構建二進制文件並運行它,而不需要使用 go run 命令。可以使用相同的鏡像來構建,或者也可以使用 Docker 的多階段構建,即使用 golang 鏡像來構建並使用迷你 linux 容器如 alpine 來運行服務。

單階段生產構建

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

構建並運行該一體化的鏡像:

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

因為底層使用了 Debian 鏡像,該鏡像會達到 750 MB 左右的大小(取決於你的源代碼)。讓我們看看如何縮減體積。

多階段生產構建

多階段構建允許你在一個完整的 OS 環境中進行構建,但構建後的二進制文件通過一個非常苗條的鏡像來運行,該鏡像僅比構建後的二進制文件略大一點而已。

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

現在二進制文件為 14 MB 左右,docker 鏡像為 18 MB 左右。真是多虧了 alpine。

想減小二進制文件體積嗎?繼續看吧。

福利:使用 UPX 來壓縮二進制文件

Hasura,我們已經在到處使用 UPX 了,壓縮後我們的 CLI 二進制文件從 50 MB 左右降到 8 MB左右,大大加快了下載速度。UPX 可以極快地進行原地解壓,不需要額外的工具,因為它將解壓器嵌入到了二進制文件內部。

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可

UPX 壓縮後的二進制文件為 3 MB 左右並且 docker 鏡像為 6 MB 左右。

相比最開始的鏡像,縮減了 100 倍

如果你有更好的建議或是你需要其他的使用場景,請在評論區留言或者去 HackerNewsReddit 進行討論。

額...你嘗試過在 Hasura 上部署 Go web-app 嗎?這真的是世界上最快的將 Go apps 部署到 HTTPS 域下的方法(僅僅 git push 就夠了)。使用這裡的項目模板快速開始吧:https://hasura.io/hub/go-frameworks。Hasura 所有項目模板都配套有 Dockerfile 和 Kubernetes spec,允許你按照你的方式來自定義。


via: https://blog.hasura.io/the-ultimate-guide-to-writing-dockerfiles-for-go-web-apps-336efad7012c

作者:Shahidh K Muhammed 譯者:ParadeTo 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

如何將 Go Web APP 部署到 Docker?掌握該文的 Dockerfile 即可


分享到:


相關文章: