你或許想在 Docker 中使用 Go,原因有:
恭喜你,你來對地方了。
我們将逐步構建一個基本的 dockerfile,包括實時重載和包管理,然後進行擴展,創建一個高度優化的生産版的鏡像,其大小縮減了 100 倍。如果你使用 CI/CD 系統,鏡像大小可能無關緊要,但是當 docker push 和 docker pull 時,一個精簡的鏡像肯定會有幫助。
如果你隻想要最終的代碼,請看 GitHub。
假設我們的應用叫 go-docker,下面是項目的結構。所有的源碼都在 src 目錄下,Dockerfile 跟它在同一級目錄。 main.go 定義了一個 web-app 并監聽 8080 端口。
最簡單的版本
我們使用 debian jessie 版本的 golang 鏡像,因為像 go get 這樣的命令需要安裝有 git 等工具。對于生産版本,我們會用更加輕量的版本,如 alpine。
構建并運行該鏡像:
成功後可以通過 http://localhost:8080 來訪問。按下 Ctrl C 可以中斷服務。
但這并沒有多大意義,因為每次修改代碼時,我們都必須構建和運行docker 鏡像。
一個更好的版本是将源代碼挂載到 docker 容器中,并使用容器内的 shell 來停止和啟動 go run。
這個命令會提供一個 shell,我們可以在裡面執行 go run src/main.go 以啟動服務。我們可以在宿主機上編輯 main.go 并重新運行該命令來查看變化,因為現在源代碼已經直接挂載到了容器中。
但是,如何管理包呢?
包管理和鏡像分層Go 的包管理 仍處在實驗階段。有很多工具可以選擇,但是我最喜歡的是 Glide。我們将在容器中安裝 Glide 并使用它。
在 go-docker 項目中新建兩個文件 glide.yaml 和 glide.lock:
按照下面所示修改 Dockerfile 并構建一個新的鏡像:
如果你觀察比較細緻,你會發現 glide.yaml 和 glide.lock 是分開添加的(并沒有用 ADD . .),這樣會導緻有單獨分離的層。将包管理分離為單獨的層,可以充分利用 Docker 層的緩存,并且隻有當對應的文件發生變化才會導緻重新編譯,比如:新增或删除了一個包。因此,glide install 不會在每次修改了代碼之後都去執行。
讓我們進入容器的 shell 安裝一個包:
Glide 會将所有包安裝到 vendor 目錄,該目錄可以被 gitignored 和 dockerignored。使用 glide.lock 來鎖定某個包的版本。要安裝(或重新安裝)glide.yaml 中提到的所有包,執行:
現在 go-docker 目錄有所增長:
實時重載
codegangsta/gin 是我最喜歡的實時重載工具。它簡直就是為 Go web 服務而生的。我們使用 go get 來安裝 gin:
構建鏡像并運行 gin 以便當我們修改了 src 中的源代碼時可以自動重新編譯:
注意到 web-server 需要一個 PORT 的環境變量來監聽,因為 gin 會随機設置 PORT 變量并代理到該端口的連接。
現在,修改 src 目錄下的内容會觸發重新編譯,所有更新的内容可以實時在 http://localhost:8080 訪問到。
一旦開發完畢,我們可以構建二進制文件并運行它,而不需要使用 go run 命令。可以使用相同的鏡像來構建,或者也可以使用 Docker 的多階段構建,即使用 golang 鏡像來構建并使用迷你 linux 容器如 alpine 來運行服務。
單階段生産構建
構建并運行該一體化的鏡像:
因為底層使用了 Debian 鏡像,該鏡像會達到 750 MB 左右的大小(取決于你的源代碼)。讓我們看看如何縮減體積。
多階段生産構建多階段構建允許你在一個完整的 OS 環境中進行構建,但構建後的二進制文件通過一個非常苗條的鏡像來運行,該鏡像僅比構建後的二進制文件略大一點而已。
現在二進制文件為 14 MB 左右,docker 鏡像為 18 MB 左右。真是多虧了 alpine。
想減小二進制文件體積嗎?繼續看吧。
福利:使用 UPX 來壓縮二進制文件在 Hasura,我們已經在到處使用 UPX 了,壓縮後我們的 CLI 二進制文件從 50 MB 左右降到 8 MB左右,大大加快了下載速度。UPX 可以極快地進行原地解壓,不需要額外的工具,因為它将解壓器嵌入到了二進制文件内部。
UPX 壓縮後的二進制文件為 3 MB 左右并且 docker 鏡像為 6 MB 左右。
相比最開始的鏡像,縮減了 100 倍
如果你有更好的建議或是你需要其他的使用場景,請在評論區留言或者去 HackerNews 和 Reddit 進行讨論。
額...你嘗試過在 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語言中文網 榮譽推出
,
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!