【容器】Docker之應用數據管理(volume/bind mount/tmpfs)

英文原文鏈接:https://docs.docker.com/engine/admin/volumes/#tips-for-using-bind-mounts-or-volumes

雖然我們可以在docker容器中保存寫入的數據,但還是有這樣幾個不足:

 

  1. 容器中的數據會隨着容器的停止運行而消失, 而且當其他的進程需要這些數據時,很難將這些數據從容器中提取出來;
  2. 容器的數據寫入層是緊密地對應着他的宿主操作系統的,數據不能容易的被遷移到其他地方;
  3. 要將數據寫入到容器的數據寫入層,需要一個特定的存儲驅動,利用linux內核構建一個統一的文件系統,來管理宿主和容器的文件系統。這層額外的虛擬化顯然會降低性能。爲了避免性能下降,docker使用data volumes的方式,直接對宿主文件系統進行寫操作。

Docker提供了三種不同的方式用於將宿主的數據掛載到容器中:volumes,bind mounts,tmpfs volumes。當你不知道該選擇哪種方式時,記住,volumes總是正確的選擇。下面將進一步介紹每種掛載方式的工作機制。

 

選擇正確的掛載類型

無論選擇哪種掛載方式,在容器內部看來,數據就是數據,並沒有什麼不同。主機的數據在容器的文件系統中總被顯示爲目錄或文件。如何簡單的理解這三種掛載方式的不同之處呢,我們可以理解爲在這三種方式下,容器內的數據在宿主機中存放的位置不同,見下圖:
 
  1. Volumes方式下:容器內的數據被存放到宿主機(linux)一個特定的目錄下(/var/lib/docker/volumes/)。這個目錄只有Docker可以管理,其他進程不能修改。如果想持久保存容器的應用數據,Volumes是Docker推薦的掛載方式。
  2. Bind mounts方式下:容器內的數據被存放到宿主機文件系統的任意位置,甚至存放到一些重要的系統目錄或文件中。除了Docker之外的進程也可以任意對他們進行修改;
  3. tmpfs方式下:容器的數據只會存放到宿主機的內存中,不會被寫到宿主機的文件系統中,因此不能持久保存容器的應用數據。

詳細介紹三種掛載方式

Volumes:
  • 由Docker進程創建和管理。可以通過命令docker volume create來創建一個指定的卷,也可以由Docker進程在創建容器或服務的過程中來創建;
  • 當你爲一個容器創建一個volume時,這個volume將會被存儲到宿主機的一個目錄下。當你掛載這個volume到一個容器中時,就是在掛載這個目錄到容器中。這和bind mount的工作機制很相似,當然,除了volume是被Docker所管理並與宿主機其他核心功能隔離之外。
  • 一個volume可以被同時掛載到多個容器中。當沒有任何容器在使用這個volume的時候,這個volume也仍然可以被Docker進程所使用,而不是自動被刪除。當然,你可以使用命令手動刪除volume:docker volume prune
  • 當你掛載一個volume時,可以選擇爲他命名(named),也可以不命名(anonymous). 如果不命名的話,當這個volume首次被掛載到一個容器中時,Docker進程會分配給它一個隨機的名字,以保證在宿主機操作系統中這個volume的名字唯一。除了名字之外,命名和不命名的volume沒有區別。
  • Volume也支持使用volume drivers,以幫助你將數據保存到遠程主機或雲上。
Bind mounts:
  • 在docker的早期版本中就存在的功能,與volumes相比,他的功能比較侷限。當使用bind mounts時,宿主機的目錄或文件被掛載到容器中。容器將按照掛載目錄或文件的絕對路徑來使用或修改宿主機的中的數據。宿主機中的目錄或文件不需要預先存在,在需要的時候會自動創建。使用Bind mounts在性能上是非常好的,但這依賴於宿主機有一個目錄妥善結構化的文件系統。如果你要創建一個新的Docker應用,我們仍推薦使用named volume的方式,因爲你無法通過Docker CLI來管理bind mounts。(警告:bind mounts是一把雙刃劍,因爲使用bind mounts的容器可以在通過容器內部的進程對主機文件系統進行修改,包括創建,修改和刪除重要的系統文件和目錄,這個功能雖然很強大,但顯然也會造成安全方面的影響,包括影響到宿主機上Docker以外的進程)
tmpfs mounts:
  • 在這種掛載方式下,容器內的應用數據將不會被持久的保存到硬盤上,其中的數據只能在某個容器的生存週期內被使用,或者用於保存一些不需要持久存儲,或一些敏感的數據信息。比如,在docker內部,swarm服務使用tmpfs方式來將secrets掛載到服務的容器中。(關於secrets,參考https://docs.docker.com/engine/swarm/secrets/)
Bind mounts和volumes都可以通過使用標誌-v或--volume來掛載到容器中,只是格式有些許不同。tmpfs可以使用標誌--tmpfs進行掛載。然而,在Docker17.06及其以上版本中,我們推薦使用--mount來對容器或服務進行這三種方式的掛載,因爲這種格式更加清晰。

Volume的適用場景

  • 多個容器間需要共享數據。如果volume沒有手動被創建,它將會在首次掛載到某個容器之前被自動創建,當容器被停止或刪除時,這個volume不會隨之被刪除。多個容器可以同時以rw或ro的方式掛載這個volume。只有手動指定刪除volume,它纔會被刪除。
  • 當宿主機並沒有專用於Docker的文件系統結構時。使用volume可以使宿主機的配置與容器的運行解耦。
  • 當你希望將數據保存到遠程主機或雲上。
  • 當你希望在不同的宿主機直接備份/恢復/遷移數據時,volume是一個很好的選擇。你可以停止運行使用volume的容器,然後直接備份volume所在的目錄即可,如/var/lib/docker/volumes/<volume-name>

bind mounts的適用場景

  • 將宿主機的系統配置文件共享給容器,這是Docker爲容器提供DNS配置的默認方式,即通過bind mounts的方式將宿主的的/etc/resolv.conf文件掛載到容器中。
  • 將宿主機開發環境中的源代碼或實驗結果共享給容器。例如:你在宿主機上進行一個項目Maven的測試,每次你在宿主機上對Maven項目進行了更改後,容器就可以直接獲取更改後的結果
  • 當你可以確定宿主機的文件系統結構應該與容器內部完全一致時。

tmpfs的適用場景

  • 當你出於安全原因,或者容器性能優化的原因(如需要寫入大量的不持久的狀態數據時),不需要容器的數據長久保存時可以使用這種方式。

使用bind mounts和volumes的小Tips

  • 如果你使用volumes的方式掛載了一個空的volume到某個容器的一個非空目錄中,則這個非空目錄中已存在的內容會被拷貝到這個volume中。類似的,如果在啓動容器時指定了一個不存在的volume,一個空的volume會被自動創建;
  • 如果使用bind mounts的方式掛載,或者用volumes的方式掛載了一個非空的volume到容器的一個非空目錄中,則容器中這個非空目錄下的內容將暫時被掛載過來的volume中的內容所覆蓋(並未被刪除),當取消掛載後,容器中那個非空目錄中的文件仍然存在。就像在linux下的/mnt目錄下如果存在一些文件,在把USB掛載到/mnt時,在/mnt下就只能看到USB中的內容而看不見原先的文件,當取消USB掛載後,再進入/mnt就可以看見原先的文件了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章