亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 docker build 中緩存“go get”

在 docker build 中緩存“go get”

Go
嚕嚕噠 2022-03-07 19:35:50
我想將我的 golang 單元測試封裝在一個 docker-compose 腳本中,因為它依賴于幾個外部服務。我的應用程序有很多依賴項,所以需要一段時間才能go get.如何以允許構建 docker 容器的方式緩存包,而無需在每次我想測試時下載所有依賴項?我的 Dockerfile:FROM golang:1.7CMD ["go", "test", "-v"]RUN mkdir -p /go/src/appWORKDIR /go/src/appCOPY . /go/src/appRUN go-wrapper downloadRUN go-wrapper install每次我想運行單元測試時,我都會docker-compose up --build backend-test在以下腳本上運行:version: '2'services:  ...  backend-test:    build:      context: .      dockerfile: Dockerfile    image: backend-test    depends_on:      ...但是現在go-wrapper download每次我想運行測試時都會調用它,并且需要很長時間才能完成。解決方案?提前致謝!
查看完整描述

2 回答

?
呼如林

TA貢獻1798條經驗 獲得超3個贊

我個人使用govendor。根據 golang 供應商約定,它將您的依賴項保存在項目內的供應商目錄中。這仍然需要在構建時復制到您的 docker 映像中。


但是有很好的理由不供應商。例如,當您構建 pkg 時,您不應該供應商。當您有不同的 pkg 使用不同版本的依賴項時,事情會變得混亂。這可以通過僅供應可執行文件來解決。


因此,如果您有充分的理由不供應商,您可以分開幾個步驟。將它們按正確的順序排列將加快速度。


您可以創建一個 shell 腳本 ( get.sh),其中包含一些go get依賴項命令。(你可以把這些放在你的 Dockerfile 中,但它們有一個行限制)


go get github.com/golang/protobuf/proto

go get github.com/pborman/uuid

go get golang.org/x/net/context

go get golang.org/x/net/http2

go get golang.org/x/net/http2/hpack

然后在您的 Dockerfile 中,您首先復制并執行 shell 腳本。每次更新 get.sh 時,它都會完全重建。它仍然運行got get ./...以確保所有依賴項都存在。但是,如果所有內容都添加到get.sh腳本中,您將獲得不錯的速度提升。


FROM golang:1.6


RUN mkdir -p /go/src/app


COPY get.sh /go/src/app


WORKDIR /go/src/app


RUN bash get.sh


COPY . /go/src/app


RUN go get ./...


CMD go test -v

一般的想法是,您在 Dockerfile 中保持經常更改的內容較低,而頂部的內容則相當穩定。即使您必須添加另一個或兩個命令。Docker 將逐行執行,直到找到需要重建的內容,然后也將執行之后的每一行。


查看完整回答
反對 回復 2022-03-07
?
智慧大石

TA貢獻1946條經驗 獲得超3個贊

我一直在尋找您問題的答案,但具有諷刺意味的是,我發現了一個我有答案的問題(如何快速運行 docker 測試)。如果您真的想要快速測試,那么理想情況下,您應該在運行它們時完全避免重建容器。但是等等,如何將新的源代碼放到容器中?卷我的朋友,卷。這是我的設置方式:


碼頭工人-compose.dev.yml:


backend-test:

  volumes:

    - .:/path/to/myapp

其中 /path/to/myapp 是圖像中的路徑,當然。您必須明確地將此圖像傳遞給開發人員:


docker-compose up -f docker-compose.dev.yml

但是現在,當您運行測試時,您將不再使用 docker-compose,而是將使用 docker exec:


docker exec -it backend-test go test

如果你做對了,你在后端測試容器中的 src 目錄將永遠是最新的,因為它實際上是一個掛載的卷。附加到正在運行的容器并運行測試應該證明比每次都啟動一個新容器要快得多。


編輯:評論者正確地指出,這只會在您的依賴項沒有改變(不需要go get)時避免重建圖像。好處是它不僅避免了重建,而且還避免了重新啟動。當我像這樣進行測試并添加依賴項時,我通常只是go get直接從我的測試控制臺。在容器中工作可能有點棘手,但一種方法是通過掛載 SSH_AUTH_SOCKgo get將 ssh 代理轉發到容器. 遺憾的是,您無法在構建期間掛載卷,因此如果您希望構建目標能夠在運行測試之前提取新的依賴項,則可能需要在映像中包含某種部署密鑰。但是,我的回答的要點是將構建和測試分開,以避免在您準備好生成最終工件之前進行完整構建。


也就是說,我想我可能理解我沒有按照您提出的方式回答問題。在 ruby 中,答案就像復制 Gemfile 和 Gemfile.lock 并運行一樣簡單bundle install --deploy,然后再復制您更改的代碼。就我個人而言,我不介意添加依賴項時的重建成本,因為我的 99% 的更改仍然不會涉及重建。也就是說,您可能會考慮使用受 golang 啟發的新 Bundler 依賴管理器:dep。安裝了 dep 后,我很確定你可以將你的Gopkg.tomland復制Gopkg.lock到你的工作目錄中,運行dep ensure,然后復制您的代碼。這只會在更新 Gopkg 時提取依賴項 - 否則 docker 將能夠重用緩存層并安裝您以前的依賴項。很抱歉長時間的編輯!


查看完整回答
反對 回復 2022-03-07
  • 2 回答
  • 0 關注
  • 310 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號