多階段構建Golang程式Docker鏡像
Docker簡介
Docker是基於Linux容器技術(LXC),使用Go語言實現的開源項目,誕生於2013年,遵循Apache2.0協議。Docker自開源後,受到廣泛的關注和討論。
Docker在開發和運維中的優勢
- 更快的交付和部署
使用Docker,開發人員可以使用鏡像來快速構建一套標準的開發環境,開發完後,測試和運維人員可以直接使用完全相同的環境來部署程式碼,實現了生產環境的無縫運行。
- 更高效的資源利用
Docker容器的運行不需要額外的虛擬化管理程式支援,它是內核級的虛擬化 ,可以實現更高的性能,同時對資源的額外需求很低。
- 更輕鬆的遷移和擴展
Docker容器幾乎可以在任意的平台上運行,支援主流的作業系統發行版本。這種兼容性讓用戶可以在不同平台之間輕鬆地遷移應用。
- 更簡單的更新管理
使用Dockerfile,只需要修改一點點配置,就可以替代以往大量的更新工作。並且所有的修改都以增量的方式被分布和更新,從而實現自動化且高效的容器管理。
首先需要知道以下幾個概念
Docker鏡像
Docker鏡像類似於虛擬機鏡像,可以將它理解為一個只讀的模板。鏡像是創建Docker容器的基礎。通過版本管理和增量的文件系統,Docker提供了一套十分簡單的機制和創建和更新現有的鏡像,用戶可以直接從網上下載一個已經做好的應用鏡像,並直接使用。
Docker容器
Docker容器類似於一個輕量級的沙箱,Docker利用容器來運行和隔離應用。容器是從鏡像創建的應用運行實例。可以將其啟動、開始、停止、刪除,而這些容器都是彼此相互隔離的,互不可見的。
可以把容器看做一個簡易版的Linux系統環境(包括root用戶許可權、進程空間、用戶空間和網路空間)以及運行在其中的應用程式打包而成的盒子。
Docker倉庫
Docker倉庫類似於程式碼倉庫,它是Docker集中存放鏡像文件的場所。它的設計理念與Git類似。Docker鏡像庫分公開倉庫和私有倉庫。最大的公開倉庫是官方提供的Docker Hub。當然,如果不想公開鏡像,可以搭建自己的私有倉庫。
Dockerfile
一般介紹完以上三個概念就結束了,但我在這裡要介紹下Dockerfile,因為鏡像的好壞很大程度取決於Dockerfile。Dockerfile是一個文本格式的配置文件,用戶可以使用Dockerfile來快速創建自定義的鏡像。
多階段構建Golang應用Docker鏡像
一般Golang的Dockerfile文件會像這樣:
# Go語言環境基礎鏡像
FROM golang:latest
# 將源碼拷貝到鏡像中
COPY server.go /go/release/
# 指定工作目錄
WORKDIR /go/release
# 編譯鏡像時,運行 go build 編譯生成 app 可執行的二進位文件
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o app server.go
# 指定容器運行時入口程式 app
ENTRYPOINT ["/go/release/app"]
這種方式構建的Docker鏡像體積非常大,構建時間長,佔用磁碟空間,部署速度慢。
本篇將使用多階段構建(multi-stage builds)
的方式來減少生成的Docker鏡像的體積。
在
多階段構建
的過程中,我們在Dockerfile使用多個FROM
指令,每個FROM
指令使用不同的基礎鏡像構成了不同階段。你可以選擇從上一個階段的產物(一般指生成的文件)複製到下一個階段,從而確保不會把不需要的東西帶到下一階段。這種方法可以有效減小Docker鏡像的大小。參考官網
以開源項目—gin+vue前後端分離項目為例,介紹Golang應用如何使用多階段構建
Docker鏡像。
項目結構圖
直接上Dockerfile
# 構建:使用golang:1.13版本
FROM golang:1.13 as build
# 容器環境變數添加,會覆蓋默認的變數值
ENV GO111MODULE=on
ENV GOPROXY=//goproxy.cn,direct
# 設置工作區
WORKDIR /go/release
# 把全部文件添加到/go/release目錄
ADD . .
# 編譯:把cmd/main.go編譯成可執行的二進位文件,命名為app
RUN GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags="-s -w" -installsuffix cgo -o app cmd/main.go
# 運行:使用scratch作為基礎鏡像
FROM scratch as prod
# 在build階段複製時區到
COPY --from=build /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 在build階段複製可執行的go二進位文件app
COPY --from=build /go/release/app /
# 在build階段複製配置文件
COPY --from=build /go/release/config ./config
# 啟動服務
CMD ["/app"]
Dockerfile各指令詳細介紹://docs.docker.com/engine/reference/builder/#usage
構建階段,以golang:1.13為基礎鏡像,把項目編譯成Linux x64位系統可執行的二進位文件(命名為app)。運行階段,把必要的配置文件和app複製到scratch鏡像中運行。最後的鏡像只包括運行階段的文件,所以體積很小,只有10多M。
- golang編譯知識
GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags="-s -w" -installsuffix cgo -o app cmd/main.go
GOOS
:目標系統為linux
CGO_ENABLED
:默認為1
,啟用C語言版本的GO編譯器,通過設置成0
禁用它
GOARCH
:32位系統為386
,64位系統為amd64
-ldflags
:用於傳遞每個go工具鏈接調用的參數。
-s
: 省略符號表和調試資訊-w
: 省略DWARF符號表
-installsuffix
:在軟體包安裝的目錄中增加後綴標識,用於區分默認版本
-o
:指定編譯後的可執行文件名稱
cmd/main.go
:main
函數所在路徑
scratch鏡像
scratch是一個空鏡像,只能用於構建其他鏡像,比如你要運行一個包含所有依賴的二進位文件,如Golang程式,可以直接使用scratch作為基礎鏡像。scratch本身是不佔空間的,所以使用它構建的鏡像大小几乎和二進位文件本身一樣大,從而讓Golang應用的Docker鏡像體積非常小。
參考://mp.weixin.qq.com/s/S1Ib08SpQbf1SCbCutUoqQ
製作Golang程式Docker鏡像
這裡直接使用Linux伺服器製作Docker鏡像,也可以使用Docker for windows在windows上製作Docker鏡像。
- 前提:Linux伺服器安裝
Docker
,Golang
(1)拉取項目
go get -x github.com/bingjian-zhu/gin-vue-admin/cmd
(2)修改配置文件
進入項目中config/config.yml
,修改database
配置,改成自己的MySQL資料庫。run-mode
運行模式改成release
。
(3)生成Docker鏡像
鏡像名字為zhubingjian/gin-vue-admin
,版本1.0
,不要漏了最後面的.
;
docker build -t zhubingjian/gin-vue-admin:1.0 .
其中zhubingjian
是我Docker Hub
的帳號,想要把鏡像上傳到自己的Docker Hub
上,鏡像名稱需要以Docker Hub帳號
+/
開頭。已經生成的鏡像可以通過tag
修改名稱。
運行指令:docker images
可以看到我們生成的Docker鏡像只有14.3M,非常小。名稱為none
的鏡像是多階段生成過程留下的鏡像,可以使用docker rmi 鏡像ID
把它刪除掉。
(4)運行鏡像
docker run -d --name gin-vue-admin -p 8000:8000 zhubingjian/gin-vue-admin:1.0
-d
:容器以守護進程的方式運行--name
:容器的名字,可以不指定名字-p
:指定宿主機器與容器的埠對應關係, 格式為「宿主埠:容器埠」,如果不指定此項,將無法訪問容器里的服務
運行指令:docker ps -a
可以看到所有容器,STATUS
顯示Up 10 seconds
,表示兩個意思:一是容器在運行;二是已經運行了10秒。如果顯示Exited 6 days
,則表示已經停止運行6天了。
目前為止,我們已經成功製作Docker鏡像且運行了。接下來把前端的VUE
項目也做成Docker鏡像並運行。
製作VUE程式Docker鏡像
- 前提:伺服器安裝
Docker
,nodejs
,npm
(1)進入vue-admin
目錄,下載npm
包
npm install
(2)修改vue-admin
目錄下的.env.production
文件,改成自己的後台介面地址
(3)發布項目,生成dist
文件夾
npm run build:prod
(4)生成Docker鏡像
docker build -t zhubingjian/vue-admin:1.0 .
(5)運行鏡像
docker run -p 80:80 -d --name vue-admin zhubingjian/vue-admin:1.0
最後,在瀏覽器上打開://zbj-home.picp.io
就可以看到程式已經在伺服器上跑了。
把鏡像推送到Docker Hub上
首先需要註冊Docker Hub帳號,我註冊時候是有坑的,註冊系統需要做人機檢測,需要翻牆才能完成。官網地址://hub.docker.com/
(1)登錄Docker Hub
docker login
然後輸入用戶名和密碼
(2)推送鏡像
docker push zhubingjian/gin-vue-admin:1.0
docker push zhubingjian/vue-admin:1.0
總結
本篇主要介紹如何使用多階段構建Golang程式的Docker鏡像,此方法可以精簡Docker鏡像。
源碼地址://github.com/Bingjian-Zhu/gin-vue-admin
參考:
- //blog.haohtml.com/archives/19334
- //blog.csdn.net/weixin_42852772/article/details/82013418
- //www.jianshu.com/p/4b345a9e768e