Docker(官網)這種比虛擬機器更輕量化的「容器」虛擬化技術,基本上算是這幾年來一個滿重要的技術。透過 Docker,他可以將需要的環境打包、建構出類似虛擬機器,但是更小、更彈性的可移植環境,在需要自動佈署的環境上,應該算是很實用的一種技術。(參考介紹、參考介紹)
不過由於工作的領域不同,所以 Heresy 其實之前都沒有去碰這一個技術;真的開始接觸到,是之前試著使用 Docker 來架設 GitLab Server 的時候開始的。
後來,Heresy 也很認真地開始搞整個 GitLab CI/CD 的架構,試著透過 GitLab 的系統來做一些程式開發的自動化建置、測試。最初,考慮到環境的熟系程度,Heresy 都是直接使用作業系統的 shell 來作為 gitlab-runner 的 executor。
<!–more–>
而在整個弄到一定程度後,也發現如果能把 runner 的 executor 改成 Docker 的話,的確是有一定程度的幫助的!
怎麼說呢?如果 Runner 是用 shell 在跑的話,基本上就要先幫 runner 的系統安裝好必要的工具、函式庫等等東西。如果有好幾台 runner、就需要每一台都各自安裝成一樣的環境;而日後如果有要更新版本、或是新增套件的話,就需要每一台各自去做調整。
假設又碰到多個專案要共用同一組 runner,但是需要的套件卻有衝突的話,那就會非常麻煩了…
雖然透過虛擬機器的確可以解決這個問題,但是虛擬機器的映像檔其實也不小,要更新時也較為麻煩,所以管理上還是沒這麼方便。
這時候,Docker 就可以解決這個問題了!
透過 Docker,可以針對不同的專案建立需要的環境、而不會影響到系統、也不容易碰到版本衝突的問題;同時,Docker 的映像檔可以直接透過 Dockerfile 來產生,相對好控制、也可以進行版本控管。而透過 Docker registry 的機制,也可以讓 gitlab-runner 自己把需要的 docker image 下載下來、建立出需要的容器,更解決了更新和佈署的問題。
研究了一下、有了一點概念之後,Heresy 就投下去玩了。針對 Linux 的 Docker 環境的部分,基本上都還算玩得很順利,目前也已經把這邊的主要專案改成用 Docker 來建置了。
但是到了 Windows 環境的時候…恩,開始碰到一堆問題了。而最後,到了寫這篇文章的時候,這些問題也沒辦法完全解決,變成只能暫時放棄的狀態了。這篇文章,基本上就是一個簡單的問題紀錄了。
Windows Docker 映像檔的肥大
剛開始玩 Linux Docker 的時候,所使用的 base-image 是 ubuntu,檔案大小不到 70MB,安裝完必要的開發環境、函式庫後,容量到達了 3.8GB 左右、Heresy 就覺得已經大的有點誇張了。
而 Windows 呢?Windows 最單純的 base-image 基本上就已經是 5GB+ 的大小(官網、例如 servercore:1903 的大小就要 12.9GB…),感覺根本是把整個基礎 OS 都包起來了?而且在這肥大的映像檔的狀況下,Windows 容器還是有版本相容性的問題(參考),真的讓 Heresy 懷疑他包這麼多檔案的目的到底是什麼? = =
(這可能是因為 Windows 有使用所謂的「Hyper-V 容器」這樣的執行模式階段的關係)
這還是沒有安裝開發環境的狀況。如果要安裝 Build Tools for Visual Studio 來建置 Visual C++ 的專案的話,還需要使用包含 .Net Framework SDK 的基底影像,其容量更是往上跳了不少。
對於比較複雜、需要工具比較多的專案,整個映像檔要弄到能用,感覺可能接近 20GB 是跑不掉的了…(到時候還得改設定才行)
某方面來說,感覺也已經快要可以和 VM 的虛擬硬碟相比了。
難以處理的程式安裝
Windows 雖然有提供 batch(cmd)和 PowerShell 等 CLI(Command-Line Interface)環境,但是基本上還是一套以圖形介面為基礎的作業系統。
但是 Docker 本身並沒有辦法支援圖形介面,所有的操作都需要以 command line 的形式來進行。
這也導致了本來在 Windows 環境下、很方便就可以完成的安裝流程,在要安裝在 Docker 上的時候,有可能會碰到各式各樣的詭異狀況。
先不說別的,光是要能成功地建立出一個包含 Build Tools for Visual Studio 的 docker image 出來,就花了 Heresy 快要一個禮拜的時間…
雖然微軟官方有提供對應的 Dockerfile 的範例(參考、參考),但是在 Heresy 這邊卻是怎樣都沒辦法建置出一個可以用的 Docker image。
直接使用官方 vs-2017 的 Dockerfile 來建置的話,不管怎麼測試,Docker 內就是看不到 C:BuildTools 這個應該要有開發工具的資料夾…更慘的是,這邊的安裝錯誤,連個錯誤訊息都不給…
後來是找到另一個範例(連結),才終於建置出一個可以用的版本(17.8GB)。
而這時,也才大概確定,Build Tools for Visual Studio 2017 大概只能搭配 mcr.microsoft.com/dotnet/framework/sdk:3.5-windowsservercore-1709 這個 base image 使用、而不能用更新版的 base-image。
雖然官方有說 Visual Studio 2017 version 15.8 以前的版本無法安裝於 1809 以後的版本,但是…現在 Visual Stduio 2017 不是已經更新到 15.9 了嗎?而且 Heresy 有試過用 1803 一樣不行啊…
老實說,這部分其實應該不能算是 Windows Docker 的問題,而是很多 Windows 程式的 installer 針對 CLI-only 的環境其實設計得並不好了…
至於其他程式(Qt、CUDA)的安裝?Heresy 還沒測試就先放棄了。
Windows Docker 的隔離模式
Windows Docker 有兩種隔離模式/運作模式(官網),一種是早期的 Hyper-V 模式,實際上就是透過小型的 Hyper-V 虛擬機器來跑。透過這樣的方式,Windows Docker 也可以在一定的程度上支援 Linux 容器,但是相對地會有一些效能、使用資源上的限制。
而從 Windows 1809 後,Windows Docker 就有支援和 Linux 一樣的 process 隔離了;在個人來看,這種模式應該才算是 Docker 最初設計的目的。
但是如果使用這種模式的話…舊版的 Windows base-image(像是現在被 VS2017 綁死的 1709…)基本上不能用,而同時也不能用 Linux 容器了。
GtLab Runner 支援度不佳
其實前面的問題大多都有解,或是可能有辦法解。但是最後讓 Heresy 放棄繼續研究下去的,是 Gitlab-Runner 本身的問題了…
當 Heresy 成功弄出第一個映像檔後,真的要掛到 GitLab-Runner 上跑的時候,就馬上碰到
ERROR: Preparation failed: could not determine windows version
的錯誤。
而查了一下,這個問題是因為 GitLab Runner 在使用 Docker 來執行的時候,針對 Windows 的支援,是針對不同版本寫死的(參考);而目前又只支援 1803 和 1809 兩個版本,所以在 Heresy 這邊主要的機器都已經升級到 1903 的情況下,就變得完全不能用了…
雖然官方看來是已經知道有這個問題了,不過看來要支援似乎還沒那麼快。而如果官方沒有想要設計一個可以跨版本的方法,那之後應該每次微軟推出大升級,都繪出一次問題了…
檔案存取的問題?
另外,之前在使用建置出來的容器想要用 bind mount(官方文件)的形式把專案拿到容器裡面建置,結果看起來似乎是以 symbolic link(SYMLINKD)的形式存在的,而在平行編譯的時候,會出現檔案存取的錯誤:
fatal error C1041: cannot open program database 'xxx.pdb'; if multiple CL.EXE write to the same .PDB file, please use /FS
這個問題除了去改專案設定還有沒有其他解法呢?恩,還不知道。
上面就是目前碰到的問題了。
而目前想到可能還可以玩的方法:
-
不要使用 Build Tools for Visual Studio 2017、而改用 2019 版,然後安裝 2017 的 toolset,看看能不能用新版的 base-image。
-
GitLab 的部分,繼續使用 shell 當作 executor、手動去執行 docker 的指令。
(元件參考)
之後…總之就再看看吧。