# Docker 和 WSL 佔了很多空間，先看清資料在哪一層

Docker 清理完顯示少用了十幾 GB，Windows 的 C 槽卻沒有立刻多出同樣空間。這時先看清測的是哪一層。映像、容器和資料磁碟區在 Docker 裡面，Linux 檔案系統可能在虛擬磁碟裡面，Windows 又把這個虛擬磁碟當成一個檔案。內部能重用的空間和外部已經釋放的容量不是同一讀數。

## 先確認 Docker 正在連線哪套環境

在終端機裡查看目前的 Docker context，再看 Docker 自己的空間統計。下面幾條只讀取資訊，不執行清理。

```powershell
docker context show
docker system df -v
docker ps -a
docker volume ls
wsl --list --verbose
```

如果連線的是遠端 Docker，這組 Docker 統計描述的是遠端環境，不是本機 C 槽。同時檢查自己是否設定了 `DOCKER_HOST` 或 `DOCKER_CONTEXT`。這些環境變數可以覆蓋連線目標，具體規則看 [Docker context 說明](https://docs.docker.com/engine/manage-resources/contexts/)。WSL 清單則用來確認本機發行版與版本。[Docker 的 WSL 後端說明](https://docs.docker.com/desktop/features/wsl/)解釋了不同安裝歷史的資料組織方式。不要假設每台電腦都有相同名稱的 Docker 資料發行版。

## 映像的大小不能逐個相加當成可釋放量

[Docker 的空間統計文件](https://docs.docker.com/reference/cli/docker/system/df/)把映像共用層和獨佔層分開。多個映像可能複用同一層，刪掉一個映像不一定釋放它顯示的全部大小。統計裡的可回收表示 Docker 按目前參考關係判斷的候選空間，不等於裡面沒有以後需要的資料。

| Docker 物件 | 通常儲存什麼 | 處理前的判斷 |
| --- | --- | --- |
| 映像 | 執行環境與程式層 | 還能拉取或按原設定重建嗎，其他容器是否使用 |
| 容器 | 程式執行個體與可寫層 | 停止的容器裡有沒有未匯出的內容 |
| 建置快取 | 先前建置可以複用的結果 | 後續建置是否接受重新下載與重算 |
| 資料磁碟區 | 資料庫、上傳檔案等持久內容 | 有沒有獨立備份，屬於哪個專案 |

兩個映像各顯示 2 GB，其中共用 1.5 GB，刪其中一個並不表示能立即釋放 2 GB。這是假設的共用層例子。資料磁碟區即使沒有被目前容器參考，也可能是你剛停掉的資料庫。不能只憑「未使用」就認定可以刪除。

## 想處理建置快取，就只處理建置快取

確認原始程式碼、相依來源和建置設定還在，接受下次建置會重新產生對應結果以後，可以使用 [Docker 的建置快取清理入口](https://docs.docker.com/reference/cli/docker/builder/prune/)。下面這一條會刪除候選建置快取。執行前閱讀互動提示，保留預設確認，不加自動同意參數。

```powershell
docker builder prune
```

它的範圍比 `docker system prune` 小。後者按[官方說明](https://docs.docker.com/reference/cli/docker/system/prune/)還會處理停止的容器、部分映像和網路。增加參數又會擴大範圍，不適合複製一條通用命令去處理所有專案。正在使用多個建置器時先確認目前建置器。清理一個環境不代表其他環境的快取也已處理。

## 資料磁碟區和完整虛擬磁碟，先準備可復原備份

資料庫優先按資料庫自己的方式匯出，再驗證能復原到隔離的測試環境。[Docker 備份文件](https://docs.docker.com/desktop/settings-and-maintenance/backup-and-restore/)明確區分映像和磁碟區。儲存或提交映像不會順便把掛載磁碟區的檔案也儲存進去。Compose 設定也只是描述執行方式，不是資料庫內容的複本。

如果需要備份 Docker Desktop 整個虛擬磁碟，先按官方流程完全停止 Docker Desktop，確認目前後端和自己設定的資料位置，再複製對應檔案。正在寫入的 VHDX 不能當作穩定備份。自己的 Ubuntu 等 WSL 發行版另行備份。[WSL 命令說明](https://learn.microsoft.com/en-us/windows/wsl/basic-commands)提供匯出方式。取消註冊發行版會移除其中的資料，不要把取消註冊當成空間清理步驟。

<figure class="blog-diagram">
  <picture>
    <source media="(max-width: 900px)" srcset="/img/blog/windows-docker-wsl-disk-space-windows-zh-mobile.webp" type="image/webp" width="768" height="1500">
    <img src="/img/blog/windows-docker-wsl-disk-space-windows-zh.webp" width="1360" height="454" loading="lazy" alt="Docker 內容的保留需求不同">
  </picture>
  <figcaption>沒有參考的資料磁碟區仍可能儲存重要內容。共用映像層也會影響一次刪除能釋放多少空間。</figcaption>
</figure>

## 比較內部使用量與 Windows 外層佔用

在自己的 WSL 發行版裡，可以用 `df -h /` 看根檔案系統的使用量，再用 `du -h --max-depth=1 /home` 看使用者目錄中的主要佔用。後者不代表全系統總量，權限與其他目錄也會影響涵蓋範圍。這些讀取可能花一些時間。先從明確的大目錄查，不要為了統計走遍所有掛載磁碟。

[微軟的 WSL 磁碟說明](https://learn.microsoft.com/en-us/windows/wsl/disk-space)解釋了虛擬磁碟按需增長。Linux 看到的容量上限不等於 Windows 已佔用量。刪除內部檔案以後，可重用空間增加，外層檔案也不一定馬上縮小。想處理外層佔用時先核對目前 WSL／Docker 版本和官方支援的操作。不要直接刪除或移動 AppData 裡的虛擬磁碟，也不要把擴大容量上限誤當成釋放 C 槽空間。想回收外層檔案佔用的空間，先在發行版內部騰出空間，再按微軟 WSL 磁碟說明和 Docker Desktop 自己的磁碟映像設定壓縮虛擬磁碟。具體命令取決於 WSL 版本和後端，按對應版本的步驟做，不要照抄一條命令。

清理以後重新看 `docker system df -v`，執行需要保留的服務，檢查資料庫記錄，再完成一次原來的建置，分別核對 Docker、Linux 和 Windows 的讀數。Mole 分析頁可以幫助定位大檔。真正處理映像、磁碟區和虛擬磁碟仍回對應工具。一般套件快取看[開發目錄的差別](/tw/windows/blog/windows-developer-caches)。


Canonical: https://mole.fit/tw/windows/blog/docker-wsl-disk-space-windows
