1. 程式人生 > 實用技巧 >關於 Docker volume 掛載時檔案或資料夾不存在的問題

關於 Docker volume 掛載時檔案或資料夾不存在的問題

背景介紹

docker volume 可以使我們在啟動docker容器時,動態的掛載一些檔案(如配置檔案), 以覆蓋映象中原有的檔案,但是,掛載一個主機上尚不存在的資料夾或者檔案到容器中會怎樣呢?這裡特意做了一下實踐,記錄實驗結果如下:

資料夾掛載

docker在資料夾掛載上的行為是統一的,具體表現為:

  • 若資料夾不存在,則先創建出資料夾(若為多層資料夾,則遞迴建立)
  • 用host上的資料夾內容覆蓋container中的資料夾內容
docker run -v /path-to-folder/A:/path-to-folder/B test-image

詳細說明如下:

host上資料夾存在,且非空

host container mount result
存在的非空資料夾A 不存在的資料夾B 先在contanier中建立資料夾B,再將A資料夾中的所有檔案copy到B中
存在的非空資料夾A 存在的非空資料夾B 先將container中資料夾B的原有內容清空,再將A中檔案copy到B中

無論container中的資料夾B是否存在, A都會完全覆蓋B的內容

host上資料夾存在,但為空

host container mount result
存在的空資料夾A 存在的非空資料夾B container中資料夾B的內容被清空

container中對應的資料夾內容被清空

host上資料夾不存在

host container mount result
不存在的資料夾A 存在的非空資料夾B 在host上建立資料夾A,container中資料夾B的內容被清空
不存在的資料夾A/B/C 存在的非空資料夾B 在host上建立資料夾A/B/C,container中資料夾B的內容被清空

container中對應的資料夾內容被清空

總結

host上資料夾一定會覆蓋container中資料夾:

host container mount result
資料夾不存在/資料夾存在但為空 資料夾不存在/存在但為空/存在且不為空 container中檔案被覆蓋(清空)
資料夾存在且不為空 資料夾不存在/存在但為空/存在且不為空 container中資料夾內容被覆蓋(原內容清空, 覆蓋為host上資料夾內容)

檔案掛載

檔案掛載與資料夾掛載最大的不同點在於:

  • docker 禁止用主機上不存在的檔案掛載到container中已經存在的檔案
  • 檔案掛載不會對同一資料夾下的其他檔案產生任何影響

除此之外, 其覆蓋行為與資料夾掛載一致,即:

  • 用host上的檔案的內容覆蓋container中的檔案的內容
docker run -v /path-to-folder/non-existent-config.js:/path-to-folder/config.js test-image # forbidden

詳細說明如下:

host上檔案不存在

host container mount result
不存在的檔案configA.js 已經存在的檔案congfigB.js 報錯,Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type. 同時會在host上生成兩個空目錄 configA.js 和 configB.js, 但是container無法啟動

host上檔案存在

host container mount result
存在的檔案configA.js 存在的檔案congfigB.js container中檔名configB.js保持不變,但是檔案內容被congfigA.js的內容覆蓋了
存在的檔案configA.js 不存在的檔案congfigB.js container中新建一個檔案configB.js,其內容為configA.js的檔案內容, configB.js所在檔案下的所有其他檔案維持不變

總結

host上檔案一定會覆蓋container中資料夾

host container mount result
不存在的檔案 已經存在的檔案 禁止行為
存在的檔案 不存在的檔案/已經存在的檔案 新增/覆蓋 (若目錄不存在則會建立目錄)

結論

資料夾掛載

  • 允許不存在的資料夾或者存在的空資料夾掛載進container, container中對應的資料夾將被清空
  • 非空資料夾掛載進container將會覆蓋container中原有資料夾

檔案掛載

  • 禁止將不存在的檔案掛載進container中已經存在的檔案上
  • 存在的檔案掛載進container中將會覆蓋container中對應的檔案, 若檔案不存在則新建

應用場景

  1. 從上面的分析可知,資料夾掛載以整個資料夾為單位進行檔案覆蓋,故可在需要將大量檔案掛載進container時使用,另外,如果掛載一個空資料夾或者不存在的資料夾,一般是做逆向使用: 即容器啟動後,可能會在容器內掛載點的資料夾下生成一些檔案(如日誌),此時,在對應的host上的資料夾內就能直接看到。
  2. 檔案掛載由於只會覆蓋單個檔案而不會影響container中同一資料夾下的其他檔案,常常被用來掛載配置檔案,以在執行時,動態的修改預設配置。

特別注意

  1. 類似對映mysql,redis的資料目錄可以對映到本地目錄的原因是,目錄裡的內容不是在容器啟動前就存在的,而是在容器啟動後生成的。如果試著在 /path-to-folder/A中事先放一些東西,然後你會發現容器啟動後,原來的檔案和容器啟動後生成的檔案是並存的。