Appearance
自從換了 ARM 架構的蘋果晶片 M2 Mac 後,在本機編譯 Docker Image 的速度大幅下降,猜測是因為架構不同,中間透過 QEMU 轉換效率極低,導致速度變慢。
最近突然想到,有沒有可能在本地開發,然後把編譯 image 的工作交給一台強大的 Windows 主機,因為手邊正好有一台幾乎只用來上網的 13700K Windows 主機,結果發現這個想法可行,而且速度比本機還「飛」快,方法也很簡單。
Windows Docker 設定
以下假設 Windows 主機的區域網路 IP 為 192.168.1.101
,請將 IP 換成你自己的:
- 安裝 Docker Desktop。
- 於 Docker Desktop 的設定中,啟用「Expose daemon on tcp://localhost:2375 without TLS」。
- 待設定生效後訪問「http://127.0.0.1:2375」,如果看到
{"message":"page not found"}
回應,表示有連線成功。 - 以你的區域網路 IP 訪問相同的 port
http://192.168.1.101:2375
,沒有得到任何回應是正常的,這是因為 Docker 跑在 Windows 的 WSL2 中,預設只允許localhost
訪問。 - 以 Admin 運行 PowerShell,執行powershell這會將 2376 port 的請求轉發到 2375,並讓 2376 port 可以被區域網路的其他電腦訪問。
netsh interface portproxy add v4tov4 listenport=2376 listenaddress=0.0.0.0 connectaddress=127.0.0.1 connectport=2375
再次訪問http://192.168.1.101:2376
,如果看到{"message":"page not found"}
回應,表示有連線成功。 - 設定防火牆,對外公開 2376 port。
打開網際網路設定找到已連線的網路 → 進行防火牆及安全設定 → 進階設定。 新增一個 Inbound Rule,設定如下:規則選「連接埠」→ 連接埠選「特定本機連接埠」→ 連接埠輸入「2376」。
完成以上設定後,如果可以在 Mac 上訪問 Windows 主機 http://192.168.1.101:2376
看到 {"message":"page not found"}
回應,表示設定成功。
Mac 開發端
Docker 指令用法都一樣,只要在指令前加上 -H
參數指定遠端 Windows 主機的 IP 與 port:
sh
docker -H 192.168.1.101:2376 image ls
只要指令有即時回應,沒有跳 error,即表示透過 docker CLI 與遠端 Windows 主機連線成功。
也可以使用 DOCKER_HOST
環境變數作為設定遠端主機 IP 與 port:
sh
export DOCKER_HOST=192.168.1.101:2376
docker buildx build --platform linux/amd64 .
docker image ls
讓我意外感到方便的有兩點:
- 只要開發端具有 push 權限,使用
docker push
作用於遠端,不需要額外的設定,就可以把 image 推到 registry server。 docker build
會把 context 傳到遠端主機,完全不需要額外的設定,而且因為是區域網路,快到就像在本機直接傳輸 context 一樣。
效能比較
於開發端與遠端各跑一次 no cache build,結果如下:
- 開發端:Building 700.2s (17/17) FINISHED → 11 分鐘 40 秒
- 遠端:Building 70.7s (17/17) FINISHED → 1 分鐘 10 秒
有這麼誇張的差異,當然跟 CPU 本身的效能也有關。
build image 當中最後一個環節是每次編譯必做的 CSS/JS 編譯、壓縮指令,直接在本機運行該指令需要 44 秒;本機 docker build 需要 336 秒;遠端 docker build 只需要 15 秒。
通常每次版本更新,需要 build image 的時候,前面幾個環節都不會變動,會被快取,只有最後一個環節會變動,所以這對我來說是幾乎就是 20 倍以上的效率提升,太舒服啦!
上述介紹的方法是應用在自家區域網路內,如果是在公開網路上,也就是把區域網路 IP 改成實體 IP 也是可以的,但請務必注意安全性,以免 image 被竊取,使用 VPN 或是其他安全機制來限制此 Windows docker host 被外部連線,Docker Host 也有 SSH 的方式可用,有興趣的讀者可搜尋關鍵字研究。