使用綁定掛載
自Docker早期以來,綁定掛載一直存在。與卷相比,綁定裝載具有有限的功能。使用綁定裝入時,主機上的文件或目錄將裝入容器中。文件或目錄由其在主機上的完整路徑或相對路徑引用。相反,當您使用卷時,會在主機上的Docker存儲目錄中創建一個新目錄,Docker會管理該目錄的內容。
該文件或目錄不需要已存在於Docker主機上。如果它尚不存在,則按需創建。綁定掛載非常高效,但它們依賴於具有特定目錄結構的主機文件系統。如果正在開發新的Docker應用程序,請考慮使用命名卷。無法使用Docker CLI命令直接管理綁定裝入。
-v
和--mount
行為之間的差異
因為-v
和--volume
flags一直是Docker的一部分,所以它們的行為無法改變。這意味着在-v
和之間存在一種不同的行為--mount
。
如果使用-v
或--volume
綁定裝載Docker主機上尚不存在的文件或目錄,請-v
為您創建端點。它始終作為目錄創建。
如果使用--mount
綁定docker主機上存在的文件或目錄,Docker 容器也不會自動為創建它,但會產生一個錯誤。
使用綁定裝載啟動容器
考慮一個具有目錄的情況,source
並在構建源代碼時將工件保存到另一個目錄中source/target/
。您希望工件可用於容器/app/
,並且您希望容器在每次在開發主機上構建源時都能訪問新構建。使用以下命令將target/
目錄綁定到容器中/app/
。從source
目錄中運行命令 。該$(pwd)
子命令將擴展到Linux或者MacOS主機的當前工作目錄。
所述--mount
和-v
以下實施例產生相同的結果。除非devtest
在運行第一個容器后刪除容器,否則不能同時運行它們。
$ docker run -d \ -it \ --name devtest \ --mount type=bind,source="$(pwd)"/target,target=/app \ nginx:latest
$ docker run -d \ -it \ --name devtest \ -v "$(pwd)"/target:/app \ nginx:latest
使用docker inspect devtest
驗證綁定安裝正確創建。尋找Mounts
部分:
"Mounts": [ { "Type": "bind", "Source": "/tmp/source/target", "Destination": "/app", "Mode": "", "RW": true, "Propagation": "rprivate" } ],
這表明mount是一個bind
mount,它顯示了正確的源和目標,它表明mount是讀寫的,並且傳播設置為rprivate
。
停止容器:
$ docker container stop devtest $ docker container rm devtest
掛載到容器上的非空目錄中
如果將bind-mount綁定到容器上的非空目錄中,則綁定裝置會隱藏目錄的現有內容。這可能是有益的,例如當想要測試新版本的應用程序而不構建新圖像時。但是,它也可能令人驚訝,並且此行為與docker卷的行為不同。
此示例設計為極端,但將容器/usr/
目錄的內容替換/tmp/
為主機上的目錄。在大多數情況下,這會導致容器無法運行。
這些--mount
和-v
示例具有相同的最終結果。
$ docker run -d \ -it \ --name broken-container \ --mount type=bind,source=/tmp,target=/usr \ nginx:latest docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "exec: \"nginx\": executable file not found in $PATH".
$ docker run -d \ -it \ --name broken-container \ -v /tmp:/usr \ nginx:latest docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "exec: \"nginx\": executable file not found in $PATH".
容器已創建但無法啟動。去掉它:
$ docker container rm broken-container
使用只讀綁定裝載
對於某些開發應用程序,容器需要寫入綁定裝入,因此更改會傳播回Docker主機。在其他時候,容器只需要讀訪問權限。
此示例修改上面的示例,但ro
通過在容器中的掛載點之后添加(默認情況下為空)選項列表,將目錄掛載為只讀綁定掛載。如果存在多個選項,請用逗號分隔。
$ docker run -d \ -it \ --name devtest \ --mount type=bind,source="$(pwd)"/target,target=/app,readonly \ nginx:latest
$ docker run -d \ -it \ --name devtest \ -v "$(pwd)"/target:/app:ro \ nginx:latest
使用docker inspect devtest
驗證綁定安裝正確創建。尋找Mounts
部分:
"Mounts": [ { "Type": "bind", "Source": "/tmp/source/target", "Destination": "/app", "Mode": "ro", "RW": false, "Propagation": "rprivate" } ],
停止容器:
$ docker container stop devtest $ docker container rm devtest
配置綁定傳播
綁定傳播默認rprivate
為綁定裝入和卷。它僅可用於綁定裝入,並且僅適用於Linux主機。綁定傳播是一個高級主題,許多用戶永遠不需要配置它。
綁定傳播是指在給定的綁定裝載或命名卷中創建的裝載是否可以傳播到該裝載的副本。考慮一個安裝點/mnt
,它也安裝在上面/tmp
。傳播設置控制是否/tmp/a
也可以使用掛載/mnt/a
。每個傳播設置都有一個遞歸對位。在遞歸的情況下,請考慮將/tmp/a
其掛載為/foo
。傳播設置控制是否/mnt/a
和/或/tmp/a
將存在。
傳播設置 | 描述 |
---|---|
shared |
原始安裝的子安裝將暴露給副本安裝,副安裝的副安裝也會傳播到原始安裝。 |
slave |
類似於共享安裝,但只在一個方向上。如果原始安裝程序公開子安裝,則副本安裝程序可以看到它。但是,如果副本裝置公開子裝載,則原始裝載無法看到它。 |
private |
山是私人的。其中的子安裝不會暴露給副本安裝,副安裝的副安裝不會暴露給原始安裝。 |
rshared |
與共享相同,但傳播也擴展到嵌套在任何原始或副本裝入點中的裝入點。 |
rslave |
與從屬相同,但傳播也延伸到嵌套在任何原始或副本裝入點中的裝入點。 |
rprivate |
默認值。與private相同,意味着原始或副本裝入點中任何位置的裝載點都不會沿任一方向傳播。 |
在可以在掛載點上設置綁定傳播之前,主機文件系統需要已經支持綁定傳播。
有關綁定傳播的更多信息,請參閱共享子樹的 Linux內核文檔。
以下示例將target/
目錄裝入容器兩次,第二個裝置同時設置ro
選項和rslave
綁定傳播選項。
$ docker run -d \ -it \ --name devtest \ --mount type=bind,source="$(pwd)"/target,target=/app \ --mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave \ nginx:latest
$ docker run -d \ -it \ --name devtest \ -v "$(pwd)"/target:/app \ -v "$(pwd)"/target:/app2:ro,rslave \ nginx:latest
現在,如果你創建/app/foo/
,/app2/foo/
也存在。