AWS帳號開戶服務 AWS ECR 磁碟空間爆滿?生命周期策略(Lifecycle Policy)清理舊鏡像指南
AWS帳號開戶服務 先搞懂:ECR 為什麼會越堆越大
AWS帳號開戶服務 很多人第一次發現 ECR「爆滿」,通常不是某一次大版本發布造成的,而是長期累積的結果。CI/CD 每次建置都會推一個新鏡像,分支很多、環境很多、標籤很多,久了之後,同一個專案在 ECR 裡可能留下幾百甚至幾千個 image。雖然 ECR 是託管服務,不是你本機的磁碟,但它一樣會產生儲存費用,也會讓倉庫管理變得混亂。
最常見的情況有三種:第一,開發分支每次 commit 都產出一個新 tag,例如 feature-xxx、build-123、pr-456;第二,發布流程保留太多歷史版本,回滾卻很少真的回到更早的版本;第三,untagged image 越積越多,因為鏡像被重新標記或流程中斷後,舊 image 仍留在倉庫裡。這些鏡像單看一個不大,堆在一起就很可觀。
更麻煩的是,ECR 的鏡像不是刪了 tag 就等於刪了內容。實際上,倉庫裡會有 layers 共享,某些鏡像刪除後可釋放的空間不一定和你想像一樣線性下降。所以面對「空間爆滿」,最重要的不是手動亂刪,而是建立一套可預期、可重複執行的清理規則。
Lifecycle Policy 是什麼,能解決什麼問題
AWS ECR 的 Lifecycle Policy,就是讓倉庫依照條件自動刪除舊鏡像的規則。它不是一個清理腳本,也不是排程任務,而是由 ECR 直接執行的保留策略。你先定義哪些鏡像要留下、哪些可以過期,之後 ECR 會依照規則判斷並清除符合條件的 image。
它最適合處理的,就是「有規律、可分類」的鏡像。像是:
- 只保留最新的 20 個開發鏡像。
- 只保留最近 30 天內推送的測試鏡像。
- 保留 release 標籤,但其他臨時 tag 自動淘汰。
- 清掉沒有 tag 的殘留鏡像,避免倉庫越來越亂。
要注意的是,Lifecycle Policy 的核心不是「刪越多越好」,而是「刪得剛好」。真正成熟的做法,是先分清楚哪些鏡像屬於可回滾資產,哪些只是流水線產物。前者要保守,後者可以積極清理。只要分類做對,ECR 不但不會爆滿,還能維持很乾淨的狀態。
Lifecycle Policy 常用的幾個條件
ECR 的規則其實不難,但要用對條件。最常用的是這幾種:
- tagStatus:指定 tagged、untagged 或 any。
- tagPrefixList:用標籤前綴篩選,例如 prod-、release-、dev-。
- countType:常見是 imageCountMoreThan 或 sinceImagePushed。
- countNumber:保留數量,或保留天數。
- AWS帳號開戶服務 countUnit:只有使用 sinceImagePushed 時才會用到,通常是 days。
這裡最容易踩坑的是 tag 設計。Lifecycle Policy 並不適合拿來做很複雜的匹配,它更適合靠命名規則管理。例如你把正式版統一命名為 release-20250101,開發版統一命名為 dev-commit-id,那政策就很好寫。反過來,如果 tag 命名毫無規律,策略就會很難維護。
先別急著刪:策略要先按倉庫生命週期來設計
很多團隊一想到節省空間,就直接設一條「超過 7 天全刪」的規則。這種做法看起來乾脆,實際上很危險。因為不是每一個鏡像都只是測試用,有些版本可能是回滾依據,有些則是某次重大發布留下的里程碑。你要先搞清楚倉庫裡不同鏡像的角色,再決定刪除節奏。
建議把鏡像分成四類:
- 正式版:要保留較多,因為可能牽涉回滾。
- 預發布 / 測試版:保留中等數量,避免佔太多空間。
- 開發版 / 分支版:保留最少,因為產生頻率最高。
- untagged:通常可以更積極清理,避免殘留。
如果你的團隊已經有 release 流程,最好的做法是讓正式版和臨時版使用不同前綴。這樣一來,Lifecycle Policy 只要看 tag prefix 就能分流,規則簡單又穩定。真正可維護的策略,通常不是最複雜的,而是最一致的。
可以直接參考的 ECR Lifecycle Policy 範例
下面是一份常見、實用的範例。它的思路是:正式版保留較多、測試版次之、開發版更少、untagged 最後清理。你可以依照團隊發版速度調整數字,但邏輯最好保持一致。
{
"rules": [
{
"rulePriority": 1,
"description": "保留最新 30 個正式版鏡像",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["prod-"],
"countType": "imageCountMoreThan",
"countNumber": 30
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 2,
"description": "保留最新 20 個測試版鏡像",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["release-"],
"countType": "imageCountMoreThan",
"countNumber": 20
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 3,
"description": "清理 14 天前的開發版鏡像",
"selection": {
"tagStatus": "tagged",
"tagPrefixList": ["dev-"],
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 14
},
"action": {
"type": "expire"
}
},
{
"rulePriority": 100,
"description": "清理 7 天前的未標記鏡像",
"selection": {
"tagStatus": "untagged",
"countType": "sinceImagePushed",
"countUnit": "days",
"countNumber": 7
},
"action": {
"type": "expire"
}
}
]
}
這份規則有幾個重點。第一,rulePriority 數字越小,優先級越高,所以正式版放前面,untagged 放最後。第二,正式版和測試版用數量保留,這樣可以避免因為發布密集,導致最近幾天全被刪掉。第三,開發版和 untagged 用天數保留,比較符合它們「短生命週期」的特性。
如果你的團隊沒有明確的 prod、release、dev 分類,也可以先從「保留最新 N 個 tagged image,加上刪除 X 天前的 untagged image」開始。先把最容易膨脹的部分控制住,再慢慢細分規則,會比一次到位來得穩。
實際設計時,最容易忽略的幾個細節
1. 不要把重要版本混進臨時 tag
很多倉庫最後不好管,不是因為鏡像太多,而是因為命名太亂。正式版如果偶爾用 dev-xxx 推送,或測試版時不時掛上 latest,Lifecycle Policy 就很難準確判斷。最好的做法是先定規範,再寫策略,而不是反過來。
2. 刪除的是 image,不是部署中的容器
有些人會擔心:把 ECR 裡的 image 刪掉,會不會影響正在跑的服務?答案是,已經部署出去的容器不會因為你刪了 registry 裡的 image 立刻停止,但如果之後需要重新拉取、回滾或重新部署,就可能出問題。所以正式版一定要留足夠的回滾窗口,不要只看空間,不看風險。
3. 不要低估 untagged 的累積速度
CI 流水線一旦中斷、標籤被重新覆蓋、某些 build 流程只推送不打標籤,untagged image 就會快速變多。這類鏡像通常沒有保留價值,卻很容易被忽略。實務上,先清 untagged 往往是最快見效的方法。
4. 保留數量要跟發版頻率對齊
如果你們一天發布 20 次,保留最新 10 個開發鏡像可能兩三個小時就被覆蓋;如果你們一週才發布一次,保留 50 個正式版又可能太多。數字沒有標準答案,真正的標準是團隊的發版節奏與回滾需求。
上線前的檢查清單
在把策略套到核心倉庫之前,建議先做一輪檢查,避免刪錯。
- 確認 tag 命名是否一致,尤其是 prod、release、dev 是否有固定前綴。
- 確認正式版是否有明確回滾窗口,例如保留最近 30 天或最近 20 個版本。
- 先挑一個非核心倉庫驗證規則,觀察刪除結果是否符合預期。
- 確認 CI/CD 流程不會依賴過舊的鏡像 tag。
- 記錄策略版本,讓日後調整時知道是哪一版規則在生效。
如果你們有多個 AWS account 或多個 region,也要留意每個倉庫是否需要不同策略。不要把所有倉庫套同一份規則,因為不同服務的鏡像密度和保存需求通常差很多。資料庫、核心 API、前端靜態站點,三者的保留策略通常不會一樣。
常見誤區:不是設定了政策就萬事大吉
Lifecycle Policy 很好用,但它不是魔法。第一個誤區,是以為設定後就會立刻清空舊鏡像。實際上,規則通常是在 ECR 的生命週期掃描中逐步生效,不是你按下儲存就瞬間結束。第二個誤區,是把政策寫得太激進,結果一兩天後回滾所需的版本已經不見了。第三個誤區,是沒先整理 tag,導致規則根本無法準確分類。
還有一個很常見的問題:有人以為刪掉 image 之後,帳單立刻大幅下降。其實儲存費用的下降通常會有延遲,而且 shared layers 釋放也不是完全同步。你會先看到倉庫整潔很多,之後才慢慢反映到成本上。這很正常,不需要誤判成「政策沒生效」。
結語:先讓規則可預期,空間問題自然會變小
ECR 爆滿不是一個單純的容量問題,而是流程設計的結果。只靠手動刪除,今天清掉一批,明天又會長出來;但如果你把 tag 規範、版本分類、保留窗口和 Lifecycle Policy 一起做好,ECR 就會從「亂堆的倉庫」變成「可控的發版資產庫」。
真正好用的策略,通常有三個特徵:能看懂、能預期、能維護。看懂,代表任何工程師都知道哪類 image 會被刪;能預期,代表回滾和發布風險可控;能維護,代表半年後你還願意碰它,而不是看到就怕。把這三件事做好,ECR 的磁碟空間問題,基本上就不會再是日常麻煩。

