關於 Docker volume 掛載時檔案或資料夾不存在的問題
阿新 • • 發佈:2021-01-20
背景介紹
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中對應的檔案, 若檔案不存在則新建
應用場景
- 從上面的分析可知,資料夾掛載以整個資料夾為單位進行檔案覆蓋,故可在需要將大量檔案掛載進container時使用,另外,如果掛載一個空資料夾或者不存在的資料夾,一般是做逆向使用: 即容器啟動後,可能會在容器內掛載點的資料夾下生成一些檔案(如日誌),此時,在對應的host上的資料夾內就能直接看到。
- 檔案掛載由於只會覆蓋單個檔案而不會影響container中同一資料夾下的其他檔案,常常被用來掛載配置檔案,以在執行時,動態的修改預設配置。
特別注意
- 類似對映mysql,redis的資料目錄可以對映到本地目錄的原因是,目錄裡的內容不是在容器啟動前就存在的,而是在容器啟動後生成的。如果試著在 /path-to-folder/A中事先放一些東西,然後你會發現容器啟動後,原來的檔案和容器啟動後生成的檔案是並存的。