Dockerfile 分層快取由上往下連鎖失效

Dockerfile 每一行指令產生一個 layer。Docker build 時檢查這層的指令與輸入檔案有沒有變,沒變就直接用快取——但一旦某層失效,它後面的所有層都會跟著失效重跑

差 36 倍的兩種寫法

# ❌ 改一個字就重裝所有套件(約 180 秒)
COPY . .
RUN npm ci
 
# ✅ 依賴清單沒變就沿用快取(約 5 秒)
COPY package*.json ./
RUN npm ci
COPY . .

黃金原則:越少改動的放越上面

  1. FROM、系統套件安裝(幾乎不變)
  2. 複製依賴清單(package.json / requirements.txt / go.mod
  3. 安裝依賴(只有依賴變了才重跑)
  4. 複製原始碼(天天在改)
  5. CMD / ENTRYPOINT

其他語言同理:Python 先 COPY requirements.txtpip install;Go 先 COPY go.mod go.sumgo mod download

查哪一層在肥

docker history my-app:1.0      # 逐層看大小與產生它的指令

⚠️ 在後面的層 rm 掉檔案不會讓 image 變小——前一層還留著那些資料。必須在同一個 RUN 裡面裝完就刪(例如 apt-get install ... && rm -rf /var/lib/apt/lists/*)。同理 apt-get update 要跟 install 寫在同一個 RUN,分開寫會因為快取拿到過期的套件索引。

搭配 多階段建置把建置工具擋在最終 image 之外 一起用。