碎碎念
之前發現一個後端執行drone會發生的問題,
偶爾發生,但一段時間總會發生一次。
多個step同時build,會造成image錯亂。
好麻煩阿…
正文
先來看幾張圖,應該就能瞭解我再說什麼了。
首先看到第一張圖,他在執行docker build的時候,會用git commit的值,當作image的tag名稱。
然後看第二張圖,直到build完image後,才會再根據你的tag去將image改成你要的tags
所以我們來想一個情境,當A、B同時執行時,他們的git commit都一樣,
A已經build完了,正要執行最後一個步驟,將git commit tag改成正常的image tag 。
此時B也剛build完,所以他也產生了一個一模一樣的 commit tag的image,那A執行最後一個步驟時,他改得到底是誰的image?
如果一個接一個step跑的話,時間大概需要 4分半,
但同步的話,只要1分半,時間快了三倍。
所以還是要想辦法解掉,本來有想幾個解法,
- 一次把程式都build一遍,放在同一個image內,
執行時,再根據參數看要執行哪個檔案。
但是他們有一種情境是只要更新其中一個功能就好,那此時全部build就不太適合。
-
在drone step時,塞tag進去,但他只會在最後一個步驟,才會改image的tag ,這招也不行
-
改plugin/gcr 了,在第一步驟時就把image的tag改掉,不要使用git commit,那就解掉這個問題了。
動手
首先找到這個image的原始碼 drone-plugins/drone-docker,然後開始改吧。
各環境main.go的package import docker 要先改掉,不改掉我不確定他會不會抓本機的package,我golang初學沒多久。
修改前
import (
"os"
"runtime"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
docker "github.com/drone-plugins/drone-docker"
)
修改後
import (
"os"
"runtime"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
docker "drone-docker"
)
然後我在docker.go上面直接加了兩行,指定了tag,這不適合所有人,
因為你們的使用情境可能跟我不太一樣,我這邊是只要push到git後,drone會自動產生tag,所以如果不指定的話,我還是有tag的值可以取得。
tag := build.Repo + ":" + build.Tags[0]
args := []string{
"build",
"--rm=true",
"-f", build.Dockerfile,
"-t", build.Name,
"-t", tag,
}
另外,如果要知道plugin/gcr裡面有什麼環境變數可以拿來用的話,
可以在drone的step上面,執行export -p
- name: publish-dev
image: plugins/gcr
pull: if-not-exists
volumes:
- name: docker
path: /var/run/docker.sock
commands:
- export -p
執行結果:
改完後,執行下面的指令先產生go 的程式。
這個go的指令,我是從.drone.yaml抄出來的。
執行前記得先設定環境變數
export GOOS=linux
export GOARCH=amd64
export CGO_ENABLED=0
export GO111MODULE=on
Go build
go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-docker ./cmd/drone-docker
go build -v -ldflags "-X main.version=${DRONE_COMMIT_SHA:0:8}" -a -tags netgo -o release/linux/amd64/drone-gcr ./cmd/drone-gcr
Docker build
將go的執行檔打包進去docker image內,
先打包到本機的docker:linux-amd64,
因為docker-gcr的dockerfile會去抓docker:linux-amd64 當作image的基底再產生檔案
docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \
--file docker/docker/Dockerfile.linux.amd64 --tag plugins/docker:linux-amd64 .
docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \
--file docker/gcr/Dockerfile.linux.amd64 --tag asia-east1-docker.pkg.dev/rouge-sms/docker-public/gcr:0.0.13 .
完成
上圖可以看到,在docker build時,會同時下兩個tag,
一個還是維持git commit的值,但另一個就是拿repository加版本號當作tag。
ref.
- DRONE_STEP_NAME not available as substitution in environment
查資料時剛好有碰到這個問題,drone_step_name一直抓不到,原因再文章內。
- 修復在多模組java項目中,平行打包鏡像時,鏡像因為同名稱被覆蓋的問題
昨天才看到有人發了個PR修復同名稱的問題,感覺跟我的頗像,但實際看了,覺得不太適合。
0 意見:
張貼留言