指南/Docker使用太多記憶體

Mac上的Docker使用太多記憶體?如何找出容器並設定上限

Atta 🐬

Vitals創辦人

發佈於

簡短回答

在Mac上,Docker會在同一台Linux虛擬機器裡執行所有容器,所以活動監視器顯示的是一個很大的程序(通常是Virtual Machine Service for Docker),而不是各個容器。若要查看是哪個容器在使用記憶體,請執行docker stats。若要限制總量,請在Docker Desktop的Settings → Resources → Advanced中調低Memory limit;預設值是Mac記憶體的一半。同一處的Resource Saver會在Docker Desktop閒置時關閉虛擬機器。Vitals是一款Mac系統監控工具,會在「容器」標籤頁中顯示每個容器的記憶體、CPU、網路和連接埠,還能從選單列停止容器。

如何找出並限制Docker的記憶體

  1. 01 打開活動監視器,按一下「記憶體」,在搜尋欄位中輸入Docker。最大的那一列,就是執行你容器的虛擬機器;使用Apple的Virtualization框架時,它的名稱是Virtual Machine Service for Docker。com.docker.backend是Docker Desktop本身。
  2. 02 在「終端機」中執行docker stats --no-stream。每一列是一個執行中的容器,MEM USAGE / LIMIT會顯示它用了多少,以及最多可以用多少。
  3. 03 停止沒在使用的容器:docker stop後面加上容器名稱,或在Compose專案的檔案夾中執行docker compose down。
  4. 04 打開Docker Desktop的Settings → Resources → Advanced,把Memory limit調低到比docker stats在最忙時顯示的數值稍高一點。套用變更後,Docker Desktop會重新啟動虛擬機器。
  5. 05 在同一個區域開啟Resource Saver,讓虛擬機器在沒有容器執行時關閉。

OrbStack、Colima、Rancher Desktop和Podman也會在虛擬機器中執行容器,各自有自己的記憶體設定。以Colima來說,colima start --memory 4會給虛擬機器4 GB。

容器是Linux的功能,所以在Mac上,每種引擎都會在一台小型Linux虛擬機器中執行容器。macOS把這台機器視為一個程序,完全不知道裡面哪個容器用了什麼。這就是為什麼活動監視器會顯示一個佔用好幾GB的程序,卻完全看不到容器,也是為什麼答案要在Docker自己的工具裡找。下表將你看到的現象,對應到它是什麼以及該怎麼做。

Docker的記憶體用到哪裡去了

你看到的這是什麼怎麼做
Virtual Machine Service for Docker,好幾GB 執行所有容器的Linux虛擬機器 在Settings → Resources → Advanced中調低Memory limit
com.docker.backend Docker Desktop本身的程序 通常很小;如果一直變大,請重新啟動Docker Desktop
沒有容器在執行,記憶體仍然很高 虛擬機器仍佔著它用過的記憶體 開啟Resource Saver,或結束Docker Desktop
某個容器接近上限 它需要更多記憶體,或有洩漏 docker stats,並為個別容器設定上限
建置映像檔時記憶體上升 建置作業在同一台虛擬機器中執行 正常;建置結束後就會下降

為什麼活動監視器只顯示一個很大的Docker程序

虛擬機器跟任何App一樣向macOS取得記憶體,最多到你設定的Memory limit。在虛擬機器裡,Linux會把這些記憶體分給你的容器,剩下的用來快取檔案,就像macOS一樣。從外面看,這些都一樣:一個程序佔著大量記憶體。

只有引擎知道如何分配,而docker stats就是向它詢問這件事。那裡的CPU %直欄是虛擬機器CPU的佔比,MEM %則是容器上限的佔比;如果容器沒有設上限,就是整台虛擬機器的佔比。

該給Docker多少記憶體

Docker Desktop預設會拿走Mac一半的記憶體:16 GB的Mac就是8 GB。一般的開發環境(一台應用程式伺服器、一個資料庫和一個快取)通常需要的少得多。像平常一樣執行你的開發環境,觀察docker stats在最忙時的總量,再把Memory limit設得比它稍高一點。

設得太低,虛擬機器裡的Linux就會停止記憶體用盡的容器。執行docker inspect --format '{{.State.OOMKilled}}'後面加上容器名稱:如果發生過這種情況,它會顯示true。請調高上限,或給那個容器單獨設定上限,免得它連帶拖垮其他容器。

為個別容器設定記憶體上限

為單一容器設定上限,可以避免有洩漏的服務佔滿虛擬機器。使用docker run時,加上--memory 512m。在Compose檔案中,為該服務設定mem_limit: 512m。容器一旦超過上限就會被停止,docker stats會在它的用量旁邊顯示上限。

為什麼Docker不歸還記憶體

停止容器會釋放虛擬機器內部的記憶體,但虛擬機器不一定會馬上把它還給macOS,所以它在活動監視器中的數值可能一直很高。Resource Saver會在Docker Desktop閒置時關閉虛擬機器,藉此歸還所有記憶體;有容器需要時,幾秒鐘就會重新啟動。結束Docker Desktop也有同樣效果。

Docker與磁碟空間

映像檔、已停止的容器、磁碟區和建置快取都存放在一個磁碟映像檔中,它會隨著你的工作變大,而在Mac上會計入系統資料。docker system df會顯示每一類佔了多少。docker system prune會移除已停止的容器、未使用的網路、懸置映像檔和建置快取;只有在確定沒有任何磁碟區存著你需要的資料時,才加上--volumes。Docker Desktop設定中Memory limit旁邊的Disk usage limit可以限制它的大小。

Vitals多了什麼

Vitals能顯示虛擬機器不會告訴macOS的資訊:每個容器的記憶體。

  • 「容器」標籤頁顯示每個容器的記憶體、CPU、網路、磁碟和已發佈的連接埠,Compose專案會歸在一起
  • 顯示最大容器和最接近上限之容器的卡片,以及依容器分類的記憶體圖表
  • Docker Desktop在App列表中是一列,已計入它的虛擬機器;按一下即可看到裡面的容器
  • 選單列下拉面板中也有這些容器,詢問後按一下即可停止容器。請參閱如何停止Docker容器
  • Docker Desktop、OrbStack、Colima、Rancher Desktop和Podman

小提醒

  • Vitals會從引擎讀取容器數值,從不啟動或移除容器。「停止」是它唯一會做的變更,而且只在你要求時才做。
  • 有引擎在執行時,就會出現這個標籤頁。
購買Vitals $15 一年更新$9,或在首發期間以$15終身使用,之後為$39。一次付清,14天內可退款。

大家常問的問題

為什麼Mac上的Docker使用這麼多記憶體?

Docker會在Linux虛擬機器中執行容器,而虛擬機器最多會用到它的Memory limit,預設是Mac記憶體的一半。請在Settings → Resources → Advanced中調低Memory limit,並執行docker stats查看哪個容器用得最多。

Virtual Machine Service for Docker是什麼?

它是Docker Desktop使用Apple的Virtualization框架時,用來執行容器的虛擬機器。它的記憶體就是容器和其中的Linux使用的全部記憶體,最多到Docker Desktop的Memory limit。

如何在Mac上限制Docker的記憶體?

在Docker Desktop中打開Settings → Resources → Advanced,調低Memory limit。若是單一容器,請使用docker run --memory 512m,或在Compose檔案中使用mem_limit: 512m。

為什麼停止容器後,Docker不歸還記憶體?

即使容器停止了,虛擬機器仍會保留一部分用過的記憶體。請開啟Resource Saver,讓虛擬機器在Docker Desktop閒置時關閉,或結束Docker Desktop。

為什麼Virtual Machine Service for Docker使用這麼多CPU?

通常是某個容器在忙,docker stats會顯示是哪一個。如果沒有容器在執行,CPU仍然很高,請結束並重新打開Docker Desktop,再更新它:在某些Docker Desktop版本中,沒有東西在執行時CPU也很高,已被回報為錯誤。

Mac上該給Docker多少記憶體?

比你的容器在最忙時的用量稍多一點,docker stats會顯示這個用量。一般的開發環境通常是2到4 GB,遠低於預設的Mac記憶體一半。

有沒有App能顯示Mac上Docker容器的記憶體?

Vitals有「容器」標籤頁,會顯示每個容器的記憶體、CPU、網路、磁碟和連接埠,支援Docker Desktop、OrbStack、Colima、Rancher Desktop和Podman。它還能在詢問後從選單列停止容器。

詞彙表中的相關條目

更多指南