跳轉到主要內容
Docker Volume bind mount 容器一刪,寫進它「可寫層」的東西就沒了。要留住資料,得把資料放到容器之外。這頁把四種落點講清楚。撥下面四種模式,看資料實際落在哪、容器刪掉還在不在:

不掛載時資料在容器可寫層

容器在唯讀映像層之上有一層「可寫層」。沒掛載時,寫進去的檔案都落在這層,走 copy-on-write(CoW):改一個既有檔案時,先把整個檔案從唯讀層複製到可寫層,再改副本。
  • 改一個 1 GB 檔案的一個 byte,也要先整檔複製,寫入密集會明顯變慢
  • 可寫層跟著容器生命週期,docker rm 就全沒。
所以資料庫、需要保留的資料、大量 I/O 的工作負載,都不該只待在容器可寫層。

三種掛載比較

維度VolumeBind mounttmpfs
定義Docker 管理的具名儲存區主機路徑直接映射進容器存於主機記憶體,不落磁碟
資料存哪/var/lib/docker/volumes/<name>/_data你指定的主機路徑主機 RAM
容器刪後資料在?在(主機上)不在
跨容器共享不可
效能(Linux)等同主機檔案系統原生等同主機原生最快(RAM I/O)
適用資料庫、持久化資料、備份遷移開發同步程式碼、注入設定檔敏感憑證、暫存快取(僅限 Linux)

具名 volume 的實體位置

Linux 上:
docker volume inspect my-vol
# "Mountpoint": "/var/lib/docker/volumes/my-vol/_data"
WSL 2 後端下,這條路徑在 docker-desktop-data 這個 WSL 虛擬機裡,不在 Windows 檔案系統,從檔案總管直接點不進去。要讀 volume 內容:
docker run --rm -v my-vol:/data alpine ls /data    # 用容器掛上去看

bind mount:-v--mount

兩種語法做同一件事,但 --mount 語義明確、官方建議優先:
# -v:簡短,但歧義多
docker run -v /host/data:/app/data:ro app

# --mount:明確指定 type,杜絕歧義
docker run --mount type=bind,source=/host/data,target=/app/data,readonly app
行為--mount type=bind-v
主機路徑不存在報錯,拒絕執行自動建一個空目錄
相對路徑(./data當 bind mount可能被當成具名 volume 名稱
-v 的相對路徑雷-v mydata:/app/data(無斜線開頭)會被當成「建一個叫 mydata 的具名 volume」,不是 bind mount。要確定是 bind mount,用絕對路徑或明確的 --mount type=bind

匿名 volume 與 Dockerfile VOLUME 的雷

-v 只給容器路徑、不給名稱,會建一個隨機 UUID 的匿名 volume。Dockerfile 的 VOLUME 指令在 docker run 時也會自動建匿名 volume 掛到那個路徑。
FROM node:20
WORKDIR /app
COPY . .
RUN npm install     # node_modules 裝進映像層
VOLUME /app         # 雷:run 時匿名 volume 掛上 /app,遮蔽掉 node_modules
docker run 時匿名 volume 掛到 /app遮蔽掉容器層裡 npm install 裝好的 node_modules,應用就跑不起來。對策:VOLUME 別宣告在會被遮蔽的路徑,或乾脆不用 VOLUME,改在 docker run / Compose 顯式掛載。 容器不帶 --rm 刪掉後,匿名 volume 會殘留成 dangling volume,用 docker volume prune 清。

docker volume 指令

docker volume create my-vol
docker volume ls
docker volume inspect my-vol      # 看 Mountpoint
docker volume rm my-vol
docker volume prune               # 清未使用的 volume(預設只清匿名)

WSL 2 的掛載效能(重要)

高 I/O 的資料(程式碼、node_modules、資料庫檔)要放在 WSL 2 的 Linux 檔案系統再 bind mount,不要從 /mnt/c(Windows 路徑)掛載
docker run -v ~/my-project:/sources app          # 正確:WSL 2 Linux 檔案系統
docker run -v /mnt/c/Users/me/project:/sources app   # 避免:跨 OS 邊界,慢
官方說明:從 Windows 檔案系統 bind mount 效能明顯較差,而且 inotify 事件只在 Linux 檔案系統上有效,掛 /mnt/c 會讓 hot reload(Vite、webpack、nodemon)收不到檔案變更而失效。高 I/O 場景優先用具名 volume 或從 WSL 2 Linux 側出發的 bind mount。

接下來

  • 效能設定docker-desktop-data VHDX 怎麼看大小、搬移。
  • Docker Compose:在 compose.yaml 裡掛 volume 與 bind mount。
官方參考:docs.docker.com/engine/storage