構建快取失效

在構建映象時,Docker 會逐步執行 Dockerfile 中的指令,並按照指定順序執行每個指令。對於每個指令,構建器會檢查是否可以從構建快取中重用該指令。

通用規則

構建快取失效的基本規則如下:

  • 構建器首先檢查基礎映象是否已快取。然後,每個後續指令都與快取層進行比較。如果沒有快取層與該指令完全匹配,則快取失效。

  • 在大多數情況下,將 Dockerfile 指令與相應的快取層進行比較就足夠了。但是,有些指令需要額外的檢查和說明。

  • 對於 ADDCOPY 指令,以及帶有繫結掛載的 RUN 指令(RUN --mount=type=bind),構建器會根據檔案元資料計算快取校驗和,以確定快取是否有效。在快取查詢期間,如果涉及的任何檔案的檔案元資料已更改,則快取會失效。

    在計算快取校驗和時,不考慮檔案的修改時間(mtime)。如果僅複製檔案的 mtime 發生變化,則快取不會失效。

  • 除了 ADDCOPY 命令外,快取檢查不檢視容器中的檔案來確定快取匹配。例如,在處理 RUN apt-get -y update 命令時,不會檢查容器中更新的檔案來確定是否存在快取命中。在這種情況下,僅使用命令字串本身來查詢匹配項。

一旦快取失效,所有後續的 Dockerfile 命令都將生成新的映象,並且不再使用快取。

如果您的構建包含多個層,並且您希望確保構建快取可重用,請儘可能將指令從不經常更改的順序排列到更經常更改的順序。

RUN 指令

RUN 指令的快取不會在構建之間自動失效。假設您的 Dockerfile 中有一個安裝 curl 的步驟:

FROM alpine:3.21 AS install
RUN apk add curl

這並不意味著您的映象中的 curl 版本始終是最新的。一週後重新構建映象仍將獲得與以前相同的軟體包。要強制重新執行 RUN 指令,您可以:

  • 確保它之前的一個層已更改
  • 在構建之前使用 docker builder prune 清除構建快取
  • 使用 --no-cache--no-cache-filter 選項

--no-cache-filter 選項允許您指定要使其快取失效的特定構建階段。

$ docker build --no-cache-filter install .

構建機密

構建秘密的內容不屬於構建快取。更改秘密的值不會導致快取失效。

如果您想在更改秘密值後強制快取失效,您可以傳遞一個帶有任意值的構建引數,當更改秘密時,您也更改該引數。構建引數確實會導致快取失效。

FROM alpine
ARG CACHEBUST
RUN --mount=type=secret,id=TOKEN,env=TOKEN \
    some-command ...
$ TOKEN="tkn_pat123456" docker build --secret id=TOKEN --build-arg CACHEBUST=1 .

秘密的屬性(例如 ID 和掛載路徑)確實參與快取校驗和,如果更改,將導致快取失效。