go服務docker實踐-縮小鏡像佔用
小張開始學習go語言啦,從服務發佈開始吧
背景: 需要發佈GO服務,所以開始編輯dockerfile,遇到了些問題,在此記錄下,一起學習吧,文檔同時更新到公衆號裏了,可以加個關注呦,寫的不對的地方請指出,3Q
1 說在前面
本文環境建立在已安裝docker服務基礎上,請先準備好docker環境
2 docker鏡像要求
我們首先思考一下雲原生對應用運行時的不同需求:
體積更小:對於微服務分佈式架構而言,更小的體積意味着更少的下載帶寬,更快的分發下載速度。
啓動速度更快:對於傳統單體應用,啓動速度與運行效率相比不是一個關鍵的指標。原因是,這些應用重啓和發佈頻率相對較低。然而對於需要快速迭代、水平擴展的微服務應用而言,更快的的啓動速度就意味着更高的交付效率,和更加快速的回滾。尤其當你需要發佈一個有數百個副本的應用時,緩慢的啓動速度就是時間殺手。對於Serverless 應用而言,端到端的冷啓動速度則更爲關鍵,即使底層容器技術可以實現百毫秒資源就緒,如果應用無法在 500ms 內完成啓動,用戶就會感知到訪問延遲。
佔用資源更少:運行時更低的資源佔用,意味着更高的部署密度和更低的計算成本。
(本次我們討論如何把體積縮小)
3 創建第一版dockerfile
在這個dockerfile中,我主要做了下面這幾件事
1 打包
爲了擺脫開發環境對打包的影響,我選擇了把打包過程放在了dockerfile中
2 啓動
在第一階段打包完成後,我們可以直接執行打包後的可執行文件
下面我們來看第一版dockerfile
FROM golang
MAINTAINER 天南
WORKDIR /go/src/git.liebaopay.com/cm/cm_ad_free
COPY . .
RUN go build main.go
EXPOSE 20020 20021 20022
CMD ["./main","./config_local.ini",":20020",":20021",":20022"]
下面我們一步一步解析此dockerfile:
# 我們以官方golang鏡像爲基礎鏡像,官方golang的gopath默認在 /go/src中,所以可以直接把我們的項目放在此# # gopath中
FROM golang
# 指定維護者名稱
MAINTAINER 天南
# 指定容器內的工作目錄,不存在目錄會自動創建
WORKDIR /go/src/git.liebaopay.com/cm/cm_ad_free
# 把dockerfile當前目錄下的所有目錄和文件都複製到上步指定的工作目錄下
COPY . .
# 開始打包
RUN go build main.go
# 暴露服務端口
EXPOSE 20020 20021 20022
# 使用cmd執行命令,這個命令映射到容器內部的命令爲 ./main ./config_local.ini :20020 :20021 :20022
CMD ["./main","./config_local.ini",":20020",":20021",":20022"]
構建鏡像,並啓動
docker build -t cm_ad_free_img_v1 .
構建個鏡像,指定tag名稱爲 cm_ad_free_img_v1
下圖可以看到,鏡像構建過程
鏡像構建成功後,我們進行啓動一個容器服務
docker run --name cm_ad_free_container_v1 -it -p 9988:20022 cm_ad_free_img_v1
下面說下參數信息
--name 指定容器名稱
-t 讓docker分配一個僞終端並綁定到容器的標準輸入上
-i 則讓容器的標準輸入保持打開
-d 會採用後臺進行
-p 爲端口映射,宿主機端口:容器端口
檢查下生成的docker鏡像
我哩個去! 這鏡像佔用也太大了,足足佔用了890Mb,原因是什麼呢? 原來我們在構建鏡像的時候,引入的golang基礎鏡像以及做了不少操作,在操作的過程中,產生了不少臨時文件,這些臨時文件在運行時是不需要的
4 鏡像瘦身
Docker 提供了 Multi-stage Build(多階段構建),可以實現鏡像瘦身。
我們把dockerfile構建過程可以簡單分爲兩個階段,
第一個階段是生成可執行文件階段,使用了golang的基礎鏡像,並做了go build操作
第二個階段是執行可執行文件階段,其實第二個階段用到了第一階段的執行文件和基礎配置,執行過程中並不再依賴golang基礎鏡像
所以我們在最終發佈的鏡像中,只包含運行程序必要的文件和配置,不包含任何編譯時的依賴,這樣就減少了鏡像的體積
我們來看第二版的dockerfile,只對增加命令進行註釋
# 引入golang作爲基礎命令並起別名爲 build
FROM golang as build
MAINTAINER 天南
WORKDIR /go/src/git.liebaopay.com/cm/cm_ad_free
COPY . .
RUN go build main.go
# 引入alphine最小linux鏡像
FROM alpine
# 設置工作目錄
WORKDIR /data/app
# 複製生成的可執行命令和一些配置文件
COPY --from=build /go/src/git.liebaopay.com/cm/cm_ad_free/main .
COPY --from=build /go/src/git.liebaopay.com/cm/cm_ad_free/config_local.ini .
COPY --from=build /go/src/git.liebaopay.com/cm/cm_ad_free/logformat_local.xml .
# !!! 注意,經測試發現alpine中缺少動態庫,經查詢後的解決方式爲創建一個軟鏈
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
EXPOSE 20020 20021 20022
CMD ["./main","./config_local.ini",":20020",":20021",":20022"]
構建鏡像後,查看下佔用磁盤,直接減少到26Mb,看來胖子變爲瘦子了,哈哈
創建容器,成功啓動服務,可以開心玩耍了 ~