關於使用docker volume掛載的注意事項

2022-09-01 18:02:06

Content

在用Docker進行持久化的儲存的時候,有兩種方式:

使用資料卷(volume

-v 容器絕對路徑

或者

-v 已經建立的volume名稱:容器絕對路徑

使用掛載點(共用宿主目錄,bind mount)

-v 宿主絕對路徑:容器絕對路徑
由於兩種方法都可以使用-v--mount引數,但是實際上兩種方式的行為區別非常大。

目錄相容性

volume只能對映容器的目錄,而bind mount方式可以是目錄也可以是檔案。

可移植性

volume的檔案系統由docker進行管理,對不同系統都可以通用相容;bind mount需要指定絕對路徑,不同的作業系統,對路徑的表述是有區別的,往往無法實現互通。

目錄替代相關

如果使用volume,那麼容器內的檔案會被保留在volume中(對應的_data資料夾)內部,也就是檔案被複制到宿主機器上;使用bind mount時,如果宿主資料夾是空的,不光容器內的檔案不會被複制到宿主機器上,容器的內容還會被覆蓋為空,對於一些容器內路徑資料夾存放config檔案的情況,宿主目錄為空會導致容器內的對應目錄被清空,造成啟動錯誤的問題。(詳細對比可以看這篇文章)。

當然,對映完成之後,不管是哪一方面新建檔案,都可以正常的反映到另一方的。

在宿主檔案不為空的情況下,都會覆蓋容器路徑的檔案。

指定位置

使用volume不能指定的volume存在的位置,這個是由docker管理的(預設/var/lib/docker/volumes/),可以通過docker的daemon.json檔案進行設定,詳情可以翻翻之前我寫的文章;而使用bind mount的情況則必須指定位置。

--volume與--mount區別

在建立bind mount的時候,使用--volume會自動建立宿主方的資料夾,而--mount不會,因此使用--mount對映不存在的目錄,會報錯。

映象儲存

之前寫過一篇有關於docker export import相關的文章,想著是執行時候增加的組態檔等內容,可以直接保留。後來發現,不管是volume還是bind mount,兩種方式都無法將檔案儲存到映象中,因此需要進行單獨的檔案儲存工作。

docker-compose

docker-compose指定的時候,有一些區別:

  • 使用bind mount的時候,宿主這邊可以使用相對路徑了(./),不需要顯示指定($PWD)
  • 可以在指定volume名稱的同時建立volume,需要使用volume:的設定項

podman相容性

在CentOS類的發行版中,從8開始,已經使用podman替代了docker,直接安裝docker的情況下會預設安裝podman,並且將docker命令全部替換成podman命令,大多數命令是通用的。有幾個地方需要注意:

  • podman是無deamon程式的,也就是沒有一個專門的守護行程,因此執行的許可權要求也更低,存檔volume的位置有區別,使用更加方便。
  • podman使用-v進行bind mount時,如果宿主機器目錄不存在,那麼podman會直接報錯,而不會自動建立檔案。

實踐指南

  • 使用docker-compose建立可以移植的系統,請使用volume。
  • 使用docker export方式匯出檔案的情況下,記住單獨儲存對映的volume或者bind mount。
  • 如果替換某一個具體組態檔,只能使用bind mount形式;否則,建議使用volume,因為這樣能夠將容器內已經有的目錄複製到volume中,防止空資料夾覆蓋容器對應資料夾導致容器啟動錯誤。
  • 為了保障對podman的相容性,請先建立宿主機需要mount的資料夾。
  • 【不建議】實現bind mount形式在linux與windows下的相容性,windows下的docker desktop可以正確解析/c/windows這樣的路徑,在linux下只需要建立相同的目錄結構就也可以實現的檔案絕對路徑在不同系統的一致性。

參考