1. Manage data in Docker
默認情況下,所有在容器內部創建的文件被存儲在一個可寫的容器層。這就意味着:
- 當容器不存在的時候,數據不能被持久化,而且在容器外部想要讀取這些數據十分困難。
- 容器的可寫的層與運行容器的主機密切相關。你不能輕易地移動數據。
- 要想把數據寫到容器的可寫層,需要一個存儲驅動來管理文件系統。存儲驅動提供一個文件系統供Linux內核調用。
Docker有兩種方式將容器中的文件存儲到主機上,這樣的話即使容器停止了,文件依然被持久化下來。這兩種方式分別是:volumes和bind mounts。如果你是在Linux上運行Docker,那么你還可以使用tmpfs mount。
2. 選擇正確的掛載類型
無論你選擇哪種掛載類型,數據看起來是一樣的。它以目錄或者容器的文件系統中的單個文件的形式暴露出來。
下面這幅圖可以幫助我們更好的理解 volumes 、 bind mounts 、 tmpfs mounts 三者的區別
- Volumes 存儲在由Docker管理的主機文件系統的一部分中(在Linux中是 /var/lib/docker/volumes/ )。非Docker進程不應該去修改這部分文件系統。Volumes是在Docker上持久化數據最好的方式。
- Bind mounts 數據可以被儲存在主機的任何地方。它們甚至可能是重要的系統文件或目錄。Docker主機或Docker容器上的非Docker進程可以隨時修改它們。
- tmpfs mounts 數據只會被存儲到主機的內存中,而且從來不會寫到文件系統上。
3. 關於掛載類型
Volumes
Volumes由Docker創建並管理。你可以用docker volume create命令顯式地創建一個volume,或者在容器或服務創建的時候創建一個volume。
當你創建了一個volume以后,它被存儲到Docker主機上的一個目錄下。當你掛載這個volume到一個容器的時候,這個目錄就是掛載到容器中的目錄。這種方式跟bind mounts很像,除了volumes被Docker管理並與主機的核心功能隔離以外。
一個volume可以同時掛載到多個容器中。當沒有一個運行中的容器使用這個volume的時候,這個volume仍然是可用的,並且不會被自動刪除。你可以用docker volume prune命令刪除未使用的volumes。
當你掛載一個volume的時候,它可能是被命名的或者匿名的。匿名的volumes在它首次被掛載到一個容器中的時候不會被指定一個明確的名字,因此Docker給它們一個隨機的名字,以保證它在Docker主機中是唯一的。關於名字,命名的和匿名的volumes在使用上是一樣的。
Volumes也支持volume驅動,可以運行你存儲數據到遠程主機或雲上。
Bind mounts
與volumes相比,bind mounts有一些功能限制。當你使用bind mount的時候,主機上的一個文件或目錄被掛載到一個容器。這個文件或目錄關聯主機上的絕對路徑。這個文件或目錄不需要事先在Docker主機上存在,如果沒有則會自動在后台創建。Bind mounts的性能非常好,但它依賴於主機的文件系統上有一個特定的目錄結構可用。如果你正在開發一個新的Docker應用,建議用volumes。你不能直接用Docker命令來直接管理bind mounts。
tmpfs mounts
一個tmpfs掛載不會持久化數據到磁盤,無論是在Docker主機上還是在容器中。容器可以在容器的生命周期中使用它來存儲非持久性狀態或敏感信息。例如,在內部,群集服務使用tmpfs掛載來將秘鑰掛載到服務的容器中。
4. volumes最佳實踐
Volumes是在Docker容器和服務中保存數據的首選方式。使用volumes的一些場景:
- 在多個運行的容器之間共享數據。如果你沒有顯式地創建一個volume,那么在它首次被掛載到一個容器中的時候會被自動創建。當容器停止或被刪除以后,這個volume仍然存在。多個容器可以掛載同一個volume,可以是讀寫或只讀的。只有當你顯式地刪除volumes的時候它們才會被刪除。
- Docker主機不保證有一個給定的目錄或文件結構。Volumes解耦從容器運行時到Docker主機之間的配置。
- 當你想要存儲你的容器的數據到一個遠程主機或雲上,而不是本地
- 當你需要備份、恢復,或者將數據從一個Docker主機移動到另一個Docker主機的時候,volumes是最好的選擇。你可以停止正在使用這個volume的容器,然后備份這個volume的目錄(例如:/var/lib/docker/volumes/<volume-name>)
5. bind mounts最佳實踐
一般而言,你應該盡可能地用volumes。Bind mounts適用於下列情形:
- 在主機和容器之間共享配置。默認情況下,通過掛載/etc/resolv.conf到每個容器上,Docker提供DNS解析到容器。
- 在Docker主機和容器之間開發環境共享源代碼和構建artifacts。例如,你可能掛載一個Maven的target/目錄到一個容器,並且每次你在Docker主機上構建Maven工程的時候,這個容器可以獲得構建后的artifacts。
- 當保證Docker主機的文件或目錄結構與容器所需的bind mounts一致時。
6. tmpfs mounts最佳實踐
當你不想要數據持久化到主機或容器的時候,tmps mounts是最好的選擇。這可能是出於安全原因,或者是為了在應用程序需要編寫大量非持久性狀態數據時保護容器的性能。
7. 文檔
https://docs.docker.com/storage/
https://docs.docker.com/storage/volumes/