文章目錄
- 1. 寫在最前面
- 1.1 具體循環依賴的例子
- 2. 報錯的位置
- 2.1 代碼快速分析
- 2.2 代碼總結
- 2.3 關于 parser 的記錄
- 3. 碎碎念
1. 寫在最前面
筆者在使用 dockerfile 多階段構建的功能時,寫出了一個「circular dependency detected on stage: xx」的錯誤。
解決方式:解耦互相依賴的構建階段即可,構建 A <=> 構建 B 兩個階段是互相依賴的,改為構建 A => 構建 B
注:「多階段構建」是 Docker 提供的一種功能,運行用戶在一個 Dockerfile 中定義多個構建階段,從而優化構鏡像的大小和構建過程的效率。通過這種方式,開發者可以在不同的階段使用不同的基礎鏡像和工具,最終只將所需要的文件和依賴項復制到最終的鏡像中。
但是,作為一個有求知精神的軟件開發工程師,筆者去翻看了一下源碼的位置。(ps: 其實就是自己感興趣 BuildKit 的源碼想要學習一下,而帶著問題學習的速度更快)
1.1 具體循環依賴的例子
FROM busybox AS stage0
COPY --from=stage0 f1 /sub/
-
FROM busybox AS stage0
: 這行代碼定義了一個名為stage0
的構建階段,并使用busybox
作為基礎鏡像。 -
COPY --from=stage0 f1 /sub/
: 這行代碼嘗試從名為stage0
的構建階段復制文件f1
到/sub/
目錄。
在這個情況下,在同一個構建階段中同時定義了一個新的階段并嘗試從該階段復制文件。這會導致 Docker 無法解析這個依賴關系,因為 stage0
還沒有完成構建就被引用了。
2. 報錯的位置
源碼倉庫:GitHub - moby/buildkit: concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit
具體位置:buildkit/frontend/dockerfile/dockerfile2llb/convert.go at master · moby/buildkit · GitHub
2.1 代碼快速分析
得益于 Github 支持了 Codespaces 讓筆者可以無需代碼下載到本地,可以直接基于 Codespaces 對 「convert_test.go」的具體 case 直接做在線 debug ,逐行分析。
注:GitHub Codespaces 是一個基于云的開發環境,允許開發者在瀏覽器中創建和使用完整的開發環境。它旨在簡化開發流程,特別是對于團隊協作和快速啟動項目。以下是 GitHub Codespaces 的一些關鍵特性和功能:
代碼 debug 效果:
注:感慨一下 Codespaces 真的香!
2.2 代碼總結
核心的循環依賴檢測邏輯代碼如下:
func validateCircularDependency(states []*dispatchState) error {var visit func(*dispatchState, []instructions.Command) []instructions.Commandif states == nil {return nil}visited := make(map[*dispatchState]struct{})path := make(map[*dispatchState]struct{})visit = func(state *dispatchState, current []instructions.Command) []instructions.Command {_, ok := visited[state]if ok {return nil}visited[state] = struct{}{}path[state] = struct{}{}for dep, c := range state.deps {next := append(current, c)if _, ok := path[dep]; ok {return next}if c := visit(dep, next); c != nil {return c}}delete(path, state)return nil}for _, state := range states {if cmds := visit(state, nil); cmds != nil {err := errors.Errorf("circular dependency detected on stage: %s", state.stageName)for _, c := range cmds {err = parser.WithLocation(err, c.Location())}return err}}return nil
}
核心分析:它使用深度優先搜索(DFS)的方式來檢測循環依賴,并在發現循環時返回一個錯誤。
注:看來不是算法沒有用,是業務邏輯的代碼中使用 DFS 這種算法的場景比較少,還是得多看源碼
2.3 關于 parser 的記錄
對于 dockerfile 的 parser 也有點興趣,后面要繼續抽個時間深入分析一下。筆者當前負責的模塊重構成一個通用的 parser 的話,代碼的復用率會更高一點。希望后面有時間可以優化改進一波
3. 碎碎念
抓住 2024 的尾巴,努力學習感興趣的知識。希望 2025 平安喜樂,萬事勝意!
-
最好的選擇是,做自己的太陽
-
幸福的秘訣是,擁有蘋果時,只在意蘋果,不去管橘子,更不要想橙子的事情。
-
終于明白朝花夕拾什么意思了,你一生追求的東西其實一開始就在,只是你后知后覺而已,人無法同時擁有青春和對于青春的感受,有些東西要靠消失才能證明它的珍貴。