默認狀況下,在容器內建立的全部文件都存儲在可寫容器層上。 這意味着:html
Docker爲容器提供了兩個選項來將文件存儲在主機中,以便即便容器中止後文件也能夠持久存儲:卷和綁定掛載。若是您在Linux上運行Docker,也可使用tmpfs掛載。若是您在Windows上運行Docker,則還可使用命名管道。node
不管您選擇使用哪一種類型的安裝,容器中的數據看起來都是相同的。 它在容器的文件系統中顯示爲目錄或單個文件。nginx
可視化卷、綁定掛載和tmpfs掛載之間的差別的一個簡單方法是考慮數據在Docker主機上的位置。docker
/var/lib/docker/volumes/
)。 非Docker進程不該修改文件系統的這一部分。卷是在Docker中持久保存數據的最佳方法。docker volume create
命令顯式建立卷,或者Docker能夠在容器或服務建立期間建立卷。建立卷時,它存儲在Docker主機上的目錄中。 將卷裝入容器時,此目錄就是裝入容器的目錄。 這相似於綁定掛載的工做方式,除了卷由Docker管理而且與主機的核心功能隔離。給定的卷能夠同時裝入多個容器中。當沒有運行的容器使用卷時,該卷仍然對Docker可用,不會自動刪除。您可使用docker volume prune
來刪除未使用的卷。掛載卷時,它多是命名的或匿名的。 匿名卷首次安裝到容器中時,不會爲其指定顯式名稱,所以Docker爲它們提供一個隨機名稱,該名稱在給定Docker主機中保證是惟一的。 除了名稱以外,命名卷和匿名卷的行爲也相同。卷還支持使用卷驅動程序,這使您能夠將數據存儲在遠程主機或雲提供商上。綁定安裝和卷均可以使用-v
或--volume
標誌安裝到容器中,可是二者的語法略有不一樣。 對於tmpfs
掛載,可使用--tmpfs
標誌。 可是,在Docker 17.06及更高版本中,建議將--mount
標誌用於容器和服務,用於綁定安裝,卷或tmpfs安裝,由於語法更清晰。ubuntu
卷是將數據持久保存在Docker容器和服務中的首選方法。 卷的一些用例包括:安全
/var/lib/docker/volumes/<volume-name>
)。一般,應儘量使用卷。 綁定安裝適用於如下類型的用例:bash
/etc/resolv.conf
從主機掛載到每一個容器中來爲容器提供DNS解析的方式。target/
目錄,而且每次在Docker主機上構建Maven項目時,該容器均可以訪問重建的工件。若是您以這種方式使用Docker進行開發,那麼您的生產Dockerfile會將生產就緒的工件直接複製到映像中,而不是依賴於綁定安裝。tmpfs掛載最適用於您不但願數據在主機或容器內持久存在的狀況。 當您的應用程序須要寫入大量非持久狀態數據時,這多是出於安全緣由或爲了保護容器的性能。服務器
若是使用綁定安裝或卷,請牢記如下幾點:app
卷是存儲Docker容器生成和使用的數據的首選機制。綁定掛載依賴於主機的目錄結構,而卷則徹底由Docker管理。與綁定裝載相比,卷有幾個優勢:ssh
此外,與將數據持久保存在容器的可寫層中相比,卷一般是更好的選擇,由於卷不會增長使用卷的容器的大小,而且卷的內容存在於給定容器的生命週期以外。
若是您的容器生成非持久狀態數據,請考慮使用tmpfs掛載以免將數據永久存儲在任何地方,並經過避免寫入容器的可寫層來提升容器的性能。
卷使用rprivate綁定傳播,而且沒法爲卷配置綁定傳播。
最初,-v
或--volume
標誌用於獨立容器,而--mount
標誌用於羣服務。 可是,從Docker 17.06開始,您還能夠將--mount
與獨立容器一塊兒使用。 一般,--mount
更爲明確和詳細。 最大的區別是-v
語法在一個字段中將全部選項組合在一塊兒,而--mount
語法將它們分開。 這是每一個標誌的語法比較。
新用戶應嘗試使用--mount語法,該語法比--volume語法更簡單。
若是須要指定卷驅動程序選項,則必須使用--mount
。
-v
或--volume
:由三個字段組成,以冒號(:)分隔。 這些字段必須以正確的順序排列,而且每一個字段的含義不是當即顯而易見的。
--mount
:由多個鍵值對組成,這些對值之間用逗號分隔,每一個鍵對均由一個<key>=<value>
元組組成。 --mount
語法比-v
或--volume
更爲冗長,可是鍵的順序並不重要,而且標誌的值更易於理解。
type
,能夠是bind、volume或tmpfs。本主題討論卷,所以類型老是volume。source
。 對於命名卷,這是卷的名稱。 對於匿名卷,將省略此字段。 能夠指定爲source
或src
。destination
將文件或目錄在容器中的安裝路徑做爲其值。 能夠指定爲destination
,dst
或target
。readonly
選項,則會致使綁定掛載以只讀形式掛載到容器中。volume-opt
選項能夠屢次指定,它採用由選項名及其值組成的鍵-值對。若是您的卷驅動程序接受逗號分隔的列表做爲選項,則必須從外部CSV解析器中轉義該值。 要轉義一個volume-opt,請用雙引號(「)包圍它,並用單引號(')包圍整個安裝參數。 例如,local驅動程序在o參數中接受安裝選項做爲逗號分隔的列表。 本示例顯示了轉義列表的正確方法。
$ docker service create \
--mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"'
--name myservice \
<IMAGE>
複製代碼
下面的示例在可能的狀況下同時顯示--mount
和-v
語法,而且首先顯示--mount
。
--mount
和-v
行爲的不一樣點與綁定掛載相反,全部卷選項均可用於--mount
和-v
標誌。 將卷與服務一塊兒使用時,僅支持--mount
。
與綁定掛載不一樣,您能夠建立和管理任何容器範圍以外的卷。
建立卷:
$ docker volume create my-vol
複製代碼
列出卷:
$ docker volume ls
local my-vol
複製代碼
檢查卷:
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
複製代碼
刪除卷:
$ docker volume rm my-vol
複製代碼
若是您使用不存在的卷啓動容器,則Docker將爲您建立該卷。 如下示例將卷myvol2
安裝到容器中的/app/
中。 下面的-v
和--mount
示例將產生相同的結果。除非在運行第一個卷以後刪除devtest
容器和myvol2
卷,不然沒法同時運行它們。
$ docker run -d \
--name devtest \
--mount source=myvol2,target=/app \
nginx:latest
複製代碼
$ docker run -d \
--name devtest \
-v myvol2:/app \
nginx:latest
複製代碼
使用docker inspect devtest
命令驗證卷是否正確的建立和掛載。看Mounts
部分:
"Mounts": [
{
"Type": "volume",
"Name": "myvol2",
"Source": "/var/lib/docker/volumes/myvol2/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
複製代碼
這代表掛載是一個卷,它顯示正確的源和目標,而且掛載是讀寫的。
中止容器並刪除卷。注意:卷刪除是一個單獨的步驟。
$ docker container stop devtest
$ docker container rm devtest
$ docker volume rm myvol2
複製代碼
啓動服務並定義卷時,每一個服務容器都使用其本身的本地卷。 若是使用本地卷驅動程序,則全部容器都不能共享此數據,可是某些卷驅動程序確實支持共享存儲。 適用於AWS的Docker和適用於Azure的Docker均使用Cloudstor插件支持持久存儲。
如下示例使用四個副本啓動nginx服務,每一個副本使用一個名爲myvol2
的本地卷。
$ docker service create -d \
--replicas=4 \
--name devtest-service \
--mount source=myvol2,target=/app \
nginx:latest
複製代碼
使用docker service ps devtest-service
驗證服務是否在運行。
$ docker service ps devtest-service
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
4d7oz1j85wwn devtest-service.1 nginx:latest
複製代碼
刪除服務,它將中止全部任務:
$ docker service rm devtest-service
複製代碼
刪除服務不會刪除該服務建立的任何卷。 卷刪除是一個單獨的步驟。
docker 服務建立命令不支持-v
或--volume
選項,當要掛載捲到服務的容器中時,必須使用--mount
.
若是你像上述的那樣啓動一個容器來建立卷,容器在掛載點存在文件和目錄(就像上述的/app/
),文件的內容就會複製到卷中,而後,容器就能夠掛載和使用捲了,其餘使用該卷的容器也能訪問預填充內容。
爲了說明這一點,此示例啓動了一個nginx容器,並使用容器的/usr/share/nginx/html
目錄的內容填充新的卷nginx-vol
,Nginx在該目錄中存儲其默認HTML內容。
--mount
和 -v
的實例有一樣的效果:
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html \
nginx:latest
複製代碼
$ docker run -d \
--name=nginxtest \
-v nginx-vol:/usr/share/nginx/html \
nginx:latest
複製代碼
在運行這兩個示例以後,運行如下命令來清理容器和卷。注意:卷刪除是一個單獨的步驟。
$ docker container stop nginxtest
$ docker container rm nginxtest
$ docker volume rm nginx-vol
複製代碼
對於某些開發應用程序,容器須要寫入綁定安裝,以便將更改傳播回Docker主機。 在其餘時候,容器僅須要對數據的讀取訪問權限。 請記住,多個容器能夠掛載相同的卷,而且能夠同時對其中一些容器進行讀寫安裝,而對其餘容器則同時進行只讀安裝。
此示例修改了上面的示例,但經過在容器中的安裝點以後將ro
添加到(默認爲空)選項列表中,將目錄做爲只讀捲進行安裝。 若是存在多個選項,請用逗號分隔。
--mount
和 -v
具備一樣的效果:
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
nginx:latest
複製代碼
$ docker run -d \
--name=nginxtest \
-v nginx-vol:/usr/share/nginx/html:ro \
nginx:latest
複製代碼
使用 docker inspect nginxtest
驗證只讀的掛載被正確的建立了。請看Mounts
部分:
"Mounts": [
{
"Type": "volume",
"Name": "nginx-vol",
"Source": "/var/lib/docker/volumes/nginx-vol/_data",
"Destination": "/usr/share/nginx/html",
"Driver": "local",
"Mode": "",
"RW": false,
"Propagation": ""
}
],
複製代碼
中止並刪除容器,而後刪除卷,卷的刪除是一個獨立的步驟:
$ docker container stop nginxtest
$ docker container rm nginxtest
$ docker volume rm nginx-vol
複製代碼
在構建容錯應用程序時,您可能須要配置同一服務的多個副本,多個副本訪問相同的文件。
開發應用程序時,有幾種方法能夠實現此目的。 一種是向您的應用程序添加邏輯,以將文件存儲在像Amazon S3這樣的雲對象存儲系統上。 另外一個方法是使用支持將文件寫入外部存儲系統(例如NFS或Amazon S3)的驅動程序來建立卷。
卷驅動程序使您能夠從應用程序邏輯中抽象底層存儲系統。 例如,若是您的服務使用帶有NFS驅動程序的卷,則能夠更新服務以使用其餘驅動程序(例如,將數據存儲在雲中),而無需更改應用程序邏輯。
使用docker volume create
建立卷時,或者啓動使用還沒有建立的卷的容器時,能夠指定卷驅動程序。 如下示例使用vieux /sshfs
卷驅動程序,首先在建立獨立卷時使用,而後在啓動建立新卷的容器時使用。
本示例假定您有兩個節點,其中第一個是Docker主機,而且可使用SSH鏈接到第二個。
在Docker主機上,安裝vieux/sshfs
插件:
$ docker plugin install --grant-all-permissions vieux/sshfs
複製代碼
此示例指定了SSH密碼,可是若是兩個主機都配置了共享密鑰,則能夠省略該密碼。 每一個卷驅動程序可能具備零個或多個可配置選項,每一個選項均使用-o標誌指定。
$ docker volume create --driver vieux/sshfs \
-o sshcmd=test@node2:/home/test \
-o password=testpassword \
sshvolume
複製代碼
此示例指定了SSH密碼,可是若是兩個主機都配置了共享密鑰,則能夠省略該密碼。 每一個卷驅動程序可能具備零個或多個可配置選項。 若是卷驅動程序要求您傳遞選項,則必須使用--mount
標誌安裝卷,而不是-v
。
$ docker run -d \
--name sshfs-container \
--volume-driver vieux/sshfs \
--mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
nginx:latest
複製代碼
本示例說明了建立服務時如何建立NFS卷。 本示例使用10.0.0.10
做爲NFS服務器,並使用/var/docker-nfs
做爲NFS服務器上的導出目錄。 請注意,指定的卷驅動程序是local
。 nfs3
$ docker service create -d \
--name nfs-service \
--mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/var/docker-nfs,volume-opt=o=addr=10.0.0.10' \
nginx:latest
複製代碼
nfs4
docker service create -d \
--name nfs-service \
--mount 'type=volume,source=nfsvolume,target=/app,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/,"volume-opt=o=10.0.0.10,rw,nfsvers=4,async"' \
nginx:latest
複製代碼
卷對於備份,還原和遷移頗有用。 使用--volumes-from
標誌來建立一個安裝該卷的新容器。
例如,建立一個名爲dbstore的新容器:
$ docker run -v /dbdata --name dbstore ubuntu /bin/bash
複製代碼
而後在下一個命令中,咱們:
/backup
$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
複製代碼
當命令完成而且容器中止時,咱們剩下了dbdata卷的備份。
使用剛剛建立的備份,您能夠將其還原到同一容器或在其餘位置建立的另外一個容器。例如,建立一個名爲dbstore2的新容器:
$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
複製代碼
而後將備份文件解壓縮到新容器的數據卷中:
$ docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
複製代碼
您可使用首選工具使用上述技術來自動執行備份,遷移和還原測試。
刪除容器後,Docker數據卷仍然存在。 有兩種類型的卷鬚要考慮:
awesome:/bar
。威力自動刪除匿名卷,使用--rm
選項。例如,下面這個命令建立一個匿名卷/foo
.當容器刪除後,Docker Engine將會刪除/foo
卷,但不是awesome
卷。
$ docker run --rm -v /foo -v awesome:/bar busybox top
複製代碼
要刪除全部未使用的卷並釋放空間:
$ docker volume prune
複製代碼