# Intellij IDEA And Docker ## Get Docker https://plugins.jetbrains.com/plugin/7724-docker 建議直接從從Intellij的plugin下載Docker ## Virtual machine path mappings for Windows and macOS hosts 舉例來說,假設您將所有綁定掛載到Docker容器的文件都放在/Users/jsmith/docker-share目錄中。您可以將這個目錄映射到虛擬機器的/dockerShare路徑,以供您的Docker引擎連接使用。這個Docker引擎將會有效地從/dockerShare目錄進行綁定掛載,因為它能夠存取您從/Users/jsmith/docker-share映射而來的文件。 作為運行容器的使用者,這不會對您造成影響,因為您仍然可以配置綁定掛載和卷,將某個路徑在您的主機機器上映射到容器內的某個路徑。然而,您無法直接將容器掛載到映射到虛擬機器之外的目錄。 例如,假設您運行一個容器並將主機上包含應用程式產出的目錄/Users/jsmith/docker-share/out映射到容器內的/usr/local/tomcat/webapps目錄。在這種情況下,Docker引擎實際上會將/dockerShare/out目錄進行掛載,因為這是它通過虛擬機器映射來存取您的文件的地方。 **這段文字在解釋一個特定情境下的限制。它指出,即使某些配置需要在主機機器和容器之間進行路徑映射(比如綁定掛載和卷),但對於主機機器之外的目錄,無法直接進行掛載。也就是說,您只能將主機上特定的目錄映射到容器中,而無法直接將容器連接到主機之外的目錄。 這可能涉及到特定容器運行環境的限制或安全考慮,需要確保容器只能訪問特定的目錄,而不能直接訪問主機的其他目錄。 ![截圖 2023-11-03 下午3.07.07.png](https://hackmd.io/_uploads/SJqB3GGmT.png) For more information about volumes and bind mounts, refer to Manage data in Docker. 在Docker中管理數據 默認情況下,在容器內創建的所有文件都存儲在可寫的容器層中。這意味著: 當該容器不再存在時,數據不會保留,如果另一個進程需要它,從容器中取出數據可能會很困難。 容器的可寫層與運行容器的主機機器緊密耦合。您無法輕鬆地將數據移動到其他地方。 將數據寫入容器的可寫層需要使用存儲驅動程序來管理文件系統。存儲驅動程序提供了一個聯合文件系統,使用Linux內核。這種額外的抽象會降低性能,相比於直接將數據寫入主機文件系統的數據卷。 Docker有兩種選擇,可以讓容器將文件存儲在主機機器上,這樣在容器停止後,這些文件仍然會保留下來:卷(volumes)和綁定掛載(bind mounts)。 此外,Docker還支持容器將文件存儲在主機機器的內存中,這樣的文件是不持久的。如果您在Linux上運行Docker,將使用tmpfs掛載來將文件存儲在主機系統內存中。如果您在Windows上運行Docker,則使用命名管道來將文件存儲在主機系統內存中。 選擇正確的掛載類型 無論您選擇使用哪種類型的掛載,從容器內部來看,數據都是一致的。它在容器的文件系統中以目錄或個別文件的形式暴露出來。 要想直觀地理解卷(volumes)、綁定掛載(bind mounts)和tmpfs掛載(tmpfs mounts)之間的區別,可以考慮數據在Docker主機上的存放位置。 ![截圖 2023-11-03 下午3.34.03.png](https://hackmd.io/_uploads/rymYzmMmT.png) Volumes 存儲在由Docker管理的主機文件系統的一部分(在Linux上為/var/lib/docker/volumes/)。非Docker進程不應修改此文件系統的此部分。卷是在Docker中保留數據的最佳方法。 綁定掛載 Bind mounts 可以存儲在主機系統的任何位置。它們甚至可以是重要的系統文件或目錄。Docker主機或Docker容器上的非Docker進程可以隨時對其進行修改。 tmpfs mounts 僅存儲在主機系統的內存中,永遠不會寫入主機系統的文件系統中。 有關掛載類型的更多細節 卷(Volumes):由Docker創建和管理。您可以使用docker volume create命令明確創建一個卷,或在創建容器或服務時Docker可以自動創建一個卷。 當您創建一個卷時,它存儲在Docker主機上的一個目錄中。當您將卷掛載到容器中時,這個目錄就被掛載到容器中。這與綁定掛載的工作方式類似,唯一的區別在於卷由Docker管理,並與主機機器的核心功能隔離開來。 一個特定的卷可以同時被掛載到多個容器中。當沒有運行中的容器使用一個卷時,該卷仍然可供Docker使用,並不會自動刪除。您可以使用docker volume prune命令刪除未使用的卷。 當您掛載一個卷時,它可以是具有命名的或匿名的。匿名卷在首次被掛載到容器中時並未被賦予明確的名稱,因此Docker會為它們隨機分配一個確保在特定的Docker主機中是唯一的名稱。除了名稱之外,具有名稱和匿名的卷在行為上是相同的。 卷還支持卷驅動程序的使用,這使您可以將數據存儲在遠程主機或雲提供商等地方。 綁定掛載(Bind mounts):從Docker早期就開始提供。與卷相比,綁定掛載的功能較為有限。當您使用綁定掛載時,主機機器上的文件或目錄被掛載到容器中。這個文件或目錄是由主機機器上的完整路徑引用的。該文件或目錄在Docker主機上不需要事先存在,如果它還不存在,它將根據需要在運行時創建。綁定掛載的性能非常高效,但它們依賴於主機機器的文件系統具有特定的目錄結構。如果您正在開發新的Docker應用程序,請考慮使用具名卷。您無法使用Docker CLI命令直接管理綁定掛載。 重要提示: 綁定掛載允許訪問敏感文件。 使用綁定掛載的一個副作用,無論好壞,都是您可以通過在容器中運行的進程來更改主機文件系統,包括創建、修改或刪除重要的系統文件或目錄。這是一種強大的能力,可能會影響主機系統上的非Docker進程,進而產生安全影響。 tmpfs掛載:tmpfs掛載不會在磁盤上保留,無論是在Docker主機還是在容器內部。它可以在容器的生命周期內被使用,以存儲非持久狀態或敏感信息。例如,內部的swarm服務使用tmpfs掛載將秘密信息掛載到服務的容器中。 命名管道:npipe掛載可以用於Docker主機和容器之間的通信。常見的用例是在容器內運行第三方工具,並使用命名管道連接到Docker引擎API。 綁定掛載和卷都可以使用-v或--volume標誌掛載到容器中,但每種掛載的語法略有不同。對於tmpfs掛載,您可以使用--tmpfs標誌。我們建議在容器和服務中都使用--mount標誌,無論是對於綁定掛載、卷還是tmpfs掛載,因為這樣的語法更清晰。 ## Good use cases for volumes Volume的良好使用案例 卷是在Docker容器和服務中持久存儲數據的首選方式。一些卷的使用案例包括: 1. 在多個運行中的容器之間共享數據。如果您沒有明確創建它,則在第一次將其掛載到容器中時將創建一個卷。當該容器停止或被刪除時,該卷仍然存在。多個容器可以同時掛載相同的卷,可以是讀寫或只讀的。只有在明確刪除時,卷才會被移除。 2. 當無法保證Docker主機具有特定的目錄或文件結構時,可以使用卷。卷可以幫助您將Docker主機的配置與容器運行時解耦。 3. 當您希望將容器的數據存儲在遠程主機或雲提供商中,而不是在本地時。 4. 當您需要從一個Docker主機備份、還原或遷移數據到另一個時,卷是更好的選擇。您可以停止使用該卷的容器,然後備份該卷的目錄(例如/var/lib/docker/volumes/<卷名稱>)。 5. 當您的應用程序需要在Docker桌面上進行高性能的IO時。卷存儲在Linux虛擬機中而不是主機中,這意味著讀取和寫入的延遲較低,吞吐量較高。 6. 當您的應用程序在Docker桌面上需要完全原生的文件系統行為時。例如,數據庫引擎需要對磁盤刷新進行精確控制以保證事務持久性。卷存儲在Linux虛擬機中並且可以保證這些條件,而綁定掛載則被遠程到macOS或Windows,其中文件系統的行為略有不同。 Bind mount的良好使用案例 一般來說,應盡可能使用卷(volumes)。綁定掛載(bind mounts)適用於以下類型的使用情況: 1. 從主機機器分享配置文件到容器中。這是Docker默認提供DNS解析給容器的方式,它將主機機器上的/etc/resolv.conf掛載到每個容器中。 2. 在Docker主機和容器之間分享源代碼或構建產物。例如,您可以將Maven的target/目錄掛載到容器中,每次在Docker主機上構建Maven項目時,容器都能訪問到重建的產物。 3. 如果您以這種方式使用Docker進行開發,則您的生產Dockerfile將直接將適用於生產的產物直接複製到映像中,而不依賴於綁定掛載。 4. 當Docker主機的文件或目錄結構可以保證與容器所需的綁定掛載一致時。 綜上所述,綁定掛載主要適用於在主機和容器之間共享特定文件或目錄,以及開發環境和容器之間的源代碼或構建產物共享。然而,在大多數情況下,建議優先使用卷以實現數據的持久存儲。 對於將Spring Boot應用程序的Maven目錄掛載到Docker容器中,通常建議使用bind mount(綁定掛載)而不是volume(卷)。 這是因為Maven目錄包含開發環境中的源代碼、配置文件等文件,這些文件可能需要在容器和主機之間進行頻繁的讀寫操作。使用bind mount可以實現主機和容器之間的即時同步,而不會導致性能問題或同步延遲。 相反,使用volume可能會導致一些限制,因為volume通常用於持久化數據,而不是用於容器和主機之間的開發環境同步。 總的來說,當您需要在容器和主機之間進行開發環境的源代碼同步時,建議使用bind mount。如果您需要將數據持久化保存,則可以考慮使用volume。 ## Tips for using bind mounts or volumes