使用go mod結合docker分層快取進行自動CI/CD

GO玩家發表於2019-03-13

喜大奔的go mod

官方背書的go mod拯救了我的程式碼潔癖症!
複製程式碼

環境

  • go v1.12
  • docker ce 18.09.0
  • gitlab ce latest

godep

寫go程式,若是僅僅是你一個人寫,或者就是寫個小工具玩兒玩兒,依賴管理對你來說可能沒那麼重要。

但是在商業的工程專案裡,多人協同,go的依賴管理就尤為重要了,之前可選的其實不太多,社群提供的實現方式大多差不多的思路,比如我之前使用的godep。所以專案中會有一個vendor資料夾來存放外部的依賴,這樣:

使用go mod結合docker分層快取進行自動CI/CD

這樣的實現方式,每次更新了外部依賴,其他人就得拉下來一大坨。。。

go mod

來看看使用官方的module來管理依賴的工程結構:

使用go mod結合docker分層快取進行自動CI/CD

是不是,清爽無比,專案也整個瘦身了!

簡單的說一下go mod help,至於開啟go mod的步驟,其他網文一大堆,就不復制了。畢竟本文是說go工程CI/CD的。

在目前go v1.12版本下,命令go mod help結果如下:

The commands are:

	download    download modules to local cache
	edit        edit go.mod from tools or scripts
	graph       print module requirement graph
	init        initialize new module in current directory
	tidy        add missing and remove unused modules
	vendor      make vendored copy of dependencies
	verify      verify dependencies have expected content
	why         explain why packages or modules are needed
複製程式碼

後面CI/CD需要用到的是download指令。

dockerfile

來看看我這個工程的dockerfile:

FROM golang:1.12 as build

ENV GOPROXY https://go.likeli.top
ENV GO111MODULE on

WORKDIR /go/cache

ADD go.mod .
ADD go.sum .
RUN go mod download

WORKDIR /go/release

ADD . .

RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -installsuffix cgo -o app main.go

FROM scratch as prod

COPY --from=build /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /go/release/app /
COPY --from=build /go/release/conf.yaml /

CMD ["/app"]
複製程式碼

我這個專案有一些外部依賴,在本地開發的時候都已調整好,並且編譯通過,在本地開發環境已經生成了兩個檔案go.modgo.sum

在dockerfile的第一步驟中,先啟動module模式,且配置代理,因為有些牆外的包服務沒有梯子的情況下也是無法下載回來的,這裡的代理域名是我自己的,有需要的也可以用。

指令RUN go mod download執行的時候,會構建一層快取,包含了該項所有的依賴。之後再次提交的程式碼中,若是go.modgo.sum沒有變化,就會直接使用該快取,起到加速構建的作用,也不用重複的去外網下載依賴了。若是這兩個檔案發生了變化,就會重新構建這個快取分層。

使用快取構建的效果:

使用go mod結合docker分層快取進行自動CI/CD

這個加速效果是很明顯的。

減小體積

go構建命令使用-ldflags="-s -w"

在官方文件:Command_Line裡面說名了-s -w引數的意義,按需選擇即可。

  • -s: 省略符號表和除錯資訊
  • -w: 省略DWARF符號表

使用go mod結合docker分層快取進行自動CI/CD

看起來效果不錯?

使用scratch映象

使用golang:1.12開發映象構建好應用後,在使用scratch來包裹生成二進位制程式。

關於最小基礎映象,docker裡面有這幾類:

  • scratch: 空的基礎映象,最小的基礎映象
  • busybox: 帶一些常用的工具,方便除錯, 以及它的一些擴充套件busybox:glibc
  • alpine: 另一個常用的基礎映象,帶包管理功能,方便下載其它依賴的包

映象瘦身最終效果

好了,看看最終構建的應用的效果:

使用go mod結合docker分層快取進行自動CI/CD

構建的映象大小為: 16.4MB

CI/CD

基於gitlab的runner來進行CI/CD,看看我的.gitlab-ci.yml配置:

before_script:
- if [[ $(whereis docker-compose | wc -l) -eq 0 ]]; then curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose; fi

# ******************************************************************************************************
# ************************************** 測試環境配置 ****************************************************
# ******************************************************************************************************

deploy-test-tour:
  stage: deploy
  tags:
    - build
  only:
    - release/v2.0
  script:
    - export PRODUCTION=false
    - docker-compose stop
    - docker-compose up -d --build


# ******************************************************************************************************
# ************************************** 生產環境配置 ****************************************************
# ******************************************************************************************************

deploy-prod-tour:
  stage: deploy
  tags:
    - release
  only:
    - master
  script:
    - export PRODUCTION=true
    - docker-compose stop
    - docker-compose up -d --build
複製程式碼

我使用docker-compose來進行容器控制,所以在before_script過程裡面增加了這一步,方便新機器的全自動化嘛。

我這個專案做了點兒工程化,所以稍微正規點兒,分出了兩個環境,測試和生產環境。分別繫結到不同的分支上。

正主就是下面執行的這三行:

export PRODUCTION=false
docker-compose stop
docker-compose up -d --build
複製程式碼
  • export控制一下臨時環境變數,方便釋出不同的環境。
  • docker-compose stop停止舊的容器
  • docker-compose up -d --build編排新的容器並啟動,會使用之前的快取分層映象,所以除了第一次構建,後面的速度都是槓槓的。

看實際的釋出截圖:

使用go mod結合docker分層快取進行自動CI/CD

首次執行,總共:1 minute 22 seconds

使用go mod結合docker分層快取進行自動CI/CD

使用快取構建,總共:33 seconds

相關文章