Image tag
| 情況 | tag |
|---|---|
有給 --version TAG |
就用 TAG,原樣不動 |
| 工作目錄乾淨 | git rev-parse HEAD |
| 有未 commit 的變更 | <sha>_uncommitted_<16 位隨機十六進位> |
ghcr.io/acme/storefront:9c1f4d0b7a2e58c3d6f1b8a4e70925d3c8b1a6f2
ghcr.io/acme/storefront:9c1f4d0b7a2e58c3d6f1b8a4e70925d3c8b1a6f2_uncommitted_4b81d0e6a37f92c5
ghcr.io/acme/storefront:v2.4.0
一次部署會用到這個 tag 三次:docker tag、krane 的 --current-sha、以及 image binding,所以三者
不可能對不起來。
uncommitted 後綴
只要 git status --porcelain 有輸出,工作目錄就算不乾淨。
後綴是隨機值,不是內容雜湊。 同一個不乾淨的工作目錄建置兩次,會得到兩個不同的 tag。這保證 同一個 tag 不會對應到不同內容,而不是拿來去重的。kamal 也是這樣做。
內容雜湊得先定義什麼算內容 — 追蹤的檔案、未追蹤的檔案、檔案權限、submodule — 只要判斷錯一次就會 重用到 tag。
帶 _uncommitted_ 的 tag 用完就丟:沒有任何 commit 重現得出它。
跟 kamal 的差別
kamal 預設不會把未 commit 的變更建進去。它從乾淨的 clone 建置,只是仍然補上 _uncommitted_ 後綴,
提醒你這個 tag 跟當下的工作目錄對不起來。只有設了 builder.context,kamal 才改從工作目錄建置。
kran 一律從工作目錄建置,因為 builder.context 預設就是 .。
一個標著 _uncommitted_、內容卻只有已 commit 程式碼的 tag,誤導的方向更危險:你以為改動上去了,
其實沒有。想要 kamal 的行為就先 commit,工作目錄乾淨的話兩邊產出的都是純 sha 的 tag。
不在 git repository 裡
# repository 還沒有任何 commit 時也是同樣的訊息
$ kran deploy
ERROR: Git could not provide an image tag in /srv/build: Command failed (exit 128): git rev-parse HEAD
fatal: not a git repository (or any of the parent directories): .git
Pass --version to set the tag explicitly.
$ kran deploy --version 2024-06-01-1
在 CI 裡
CI 的 checkout 是乾淨的,推導出來就是 commit sha。checkout 是 shallow 或 detached 時,明確指定 比較保險:
kran build push --version "$GITHUB_SHA"
kran deploy --version "$GITHUB_SHA" -P
在模板裡怎麼用
image: <%= image %> # ghcr.io/acme/storefront:9c1f4d0...
labels:
app.kubernetes.io/version: <%= current_sha %>
image 是完整位址,current_sha 只有 tag。見
krane 模板。