使用volumes
卷是保存Docker容器生成和使用的數據的首選機制。mount binds依賴於主機的目錄結構,而卷完全由Docker管理。卷綁定安裝有幾個優點:
- 與綁定裝入相比,卷更易於備份或遷移。
- 您可以使用Docker CLI命令或Docker API管理卷。
- 卷適用於Linux和Windows容器。
- 可以在多個容器之間更安全地共享卷。
- 卷驅動程序允許您在遠程主機或雲提供程序上存儲卷,加密卷的內容或添加其他功能。
- 新卷可以通過容器預先填充其內容。
此外,卷通常是用在容器的可寫層中持久數據更好的選擇,因為卷不會增加使用它的容器的大小,並且卷的內容存在於給定容器的生命周期之外。
如果容器生成非持久狀態數據,請考慮使用 tmpfs掛載以避免將數據永久存儲在任何位置,並通過避免寫入容器的可寫層來提高容器的性能。
卷使用rprivate
綁定傳播,並且卷不可配置綁定傳播。
選擇-v或--mount標志
最初,-v
或者--volume
標志用於獨立容器,--mount
標志用於群集服務。但是,從Docker 17.06開始,您還可以使用--mount掛載
獨立容器。一般來說, --mount
更明確和冗長。最大的區別在於-v
語法將所有選項組合在一個字段中,而--mount
語法將它們分開。以下是每個標志的語法比較。
新用戶應該嘗試
--mount
比--volume
語法更簡單的語法。
如果需要指定卷驅動程序選項,則必須使用--mount
。
-v
或--volume
:由三個字段組成,用冒號字符(:
)分隔。字段必須按正確的順序排列,並且每個字段的含義不是很明顯。- 對於命名卷,第一個字段是卷的名稱,並且在給定主機上是唯一的。對於匿名卷,省略第一個字段。
- 第二個字段是文件或目錄在容器中安裝的路徑。
- 第三個字段是可選的,是逗號分隔的選項列表,例如
ro
。這些選項將在下面討論。
--mount
:由多個鍵值對組成,以逗號分隔,每個鍵<key>=<value>
組由一個元組組成。--mount
語法比-v
或--volume
更詳細的,但鍵的順序並不明顯,並且標志的鍵值更容易理解。
轉義外部CSV解析器的值
如果您的卷驅動程序接受以逗號分隔的列表作為選項,則必須從外部CSV解析器中轉義該值。要轉義一個 volume-opt
,用雙引號括起來("
)並用單引號括起整個mount參數('
)。
例如,local
驅動程序接受mount選項作為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語法,並
給出了--mount
和-v
語法
-v
和--mount
行為之間的差異
與綁定掛載相反,卷的所有選項都可用於--mount 標記和-v
標記。
使用具有服務的卷時,僅--mount
支持。
創建和管理卷
與bind mounts不同,您可以創建和管理任何容器范圍之外的卷。
創建一個卷
[root@benjamincloud ~]# docker volume create my-vol
my-vol
列出卷:
[root@benjamincloud ~]# docker volume ls DRIVER VOLUME NAME local my-vol
檢查卷:
[root@benjamincloud ~]# docker volume inspect my-vol [ { "CreatedAt": "2018-08-21T13:36:33+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/my-vol/_data", "Name": "my-vol", "Options": {}, "Scope": "local" } ]
刪除卷:
[root@benjamincloud ~]# docker volume rm my-vol my-vol
啟動具有卷的容器
如果啟動具有尚不存在的卷的容器,Docker會為您創建卷。以下示例將卷myvol2
裝入 /app/
容器中。
所述-v
和--mount
以下實驗產生相同的結果。只有在刪除第一個容器和卷才能執行下一個testdev,否則不能同時運行它們。
--mount 方式:
[root@benjamincloud ~]# docker run -d --name devtest --mount source=myvol2,target=/app nginx:latest c7e40bded7d029a9523bd8e0aa145741509c81dff54780adfd4e79aba5d92eb8
使用docker inspect devtest
驗證創建卷並安裝正確。尋找Mounts
部分:
這表明mount是一個卷,它顯示正確的源和目標,並且mount是可讀寫的。
停止容器並移除卷。注意刪除卷是一個單獨的步驟。
[root@benjamincloud ~]# docker stop devtest devtest [root@benjamincloud ~]# docker rm devtest devtest [root@benjamincloud ~]# docker volume rm myvol2 myvol2
使用 -v or --volume 的方式:
[root@benjamincloud ~]# docker run -d --name devtest -v myvol2:/app nginx:latest
27ecdae2edc59bcd7521ec257913fb70586d49aa014e45240a7c468289ac7849
使用docker inspect devtest
驗證創建卷並安裝正確。尋找Mounts
部分:
結果是和 --mount 掛載方式是一致的。
停止刪除容器,刪除卷
使用卷啟動服務
啟動服務並定義卷時,每個服務容器都使用自己的本地卷。如果使用local
卷驅動程序,則所有容器都不能共享此數據,但某些卷驅動程序確實支持共享存儲。Docker for AWS和Docker for Azure都使用Cloudstor插件支持持久存儲。
以下示例啟動nginx
具有四個副本的服務,每個副本使用一個名為的本地卷myvol2
。
[root@benjamincloud ~]# docker service create -d --replicas=4 --name dev-test-service --mount src=myvol2,dst=/app nginx:latest
使用docker service ps devtest-service
驗證服務正在運行:
刪除服務,停止其所有任務:
[root@benjamincloud ~]# docker service rm dev-test-service dev-test-service
刪除服務不會刪除該服務創建的任何卷。去除卷是一個單獨的步驟。
[root@benjamincloud ~]# docker volume rm myvol2 myvol2
服務的語法差異
該docker service create
命令不支持-v
或--volume
標志。將卷安裝到服務的容器中時,必須使用該--mount
標志。
使用容器填充卷
如果啟動一個創建新卷的容器(如上所述),並且容器在要掛載的目錄中具有文件或目錄(/app/
如上所述),則將目錄的內容復制到卷中。然后容器安裝並使用該卷,而使用該卷的其他容器也可以訪問預先填充的內容。
為了說明這一點,此示例啟動一個nginx
容器,並nginx-vol
使用容器/usr/share/nginx/html
目錄的內容 填充新卷,這是Nginx存儲其默認HTML內容的位置。
這些--mount
和-v
示例具有相同的最終結果。
--mount 方式:
[root@benjamincloud ~]# docker run -d --name nginxtest --mount source=nginx-vol,target=/usr/share/nginx/html nginx:latest
停止刪除容器,刪除卷之后演示 -v 或者--volume 方式
[root@benjamincloud _data]# docker stop nginxtest nginxtest [root@benjamincloud _data]# docker rm nginxtest nginxtest
[root@benjamincloud _data]# docker volume rm nginx-vol
nginx-vo
-v --volume 方式:
[root@benjamincloud _data]# docker run -d --name nginx --volume nginx-vol:/usr/share/nginx/html nginx:latest
728cf9b2d7a0b3bc563e11767c09b188d8fcfc19098d238aa123788458b0f24c
使用 docker inspect nginxtest 查看mount 數據
}, "Mounts": [ { "Type": "volume", "Name": "nginx-vol", "Source": "/var/lib/docker/volumes/nginx-vol/_data", "Destination": "/usr/share/nginx/html", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" } ],
root@benjamincloud ~]# cd /var/lib/docker/volumes/nginx-vol/_data [root@benjamincloud _data]# ls 50x.html index.html
兩種標志的掛載 達到的效果是一致的。
使用只讀卷
對於某些開發應用程序,容器需要寫入bind mounts,以便將更改傳播回Docker主機。在其他時候,容器只需要對數據的讀訪問權。請記住,多個容器可以安裝相同的卷,並且可以為其中一些容器以讀寫方式掛載,同時為其他容器以只讀方式掛載。
此示例修改上面的一個,但通過在容器中的掛載點之后添加 ro(默認為空)選項列表,將目錄掛載為只讀卷。如果存在多個選項,請用逗號分隔。
這些--mount
和-v
示例具有相同的結果。
[root@benjamincloud ~]# docker run -d --name nginx-test --mount source=nginx-vol,target=/usr/share/nginx/html,readonly nginx:latest 85848e9a91176323ed8ee954c4663bf039889037648b360e374822b71cd0a487
[root@benjamincloud ~]# docker run -d --name nginx-test --volume nginx-vol:/usr/share/nginx/html:ro nginx:latest
9e314ab6058c968c39ae713367dfb87e9ef6bac7706e32168cf40bcb143c2f80
停止並取出容器,然后取出卷。去除卷是一個單獨的步驟。
$ docker container stop nginxtest $ docker container rm nginxtest $ docker volume rm nginx-vol
在機器之間共享數據
構建容錯應用程序時,可能需要配置同一服務的多個副本才能訪問相同的文件。
在開發應用程序時,有幾種方法可以實現此目的。一種是為應用程序添加邏輯,以將文件存儲在Amazon S3等雲對象存儲系統上。另一種方法是使用支持將文件寫入NFS或Amazon S3等外部存儲系統的驅動程序創建卷。
卷驅動程序允許您從應用程序邏輯中抽象底層存儲系統。例如,如果您的服務使用具有NFS驅動程序的卷,則可以更新服務以使用其他驅動程序,例如在雲中存儲數據,而無需更改應用程序邏輯。
使用volume驅動程序
使用創建卷時docker volume create
,或者啟動使用尚未創建的卷的容器時,可以指定卷驅動程序。以下示例使用vieux/sshfs
卷驅動程序,首先在創建獨立卷時使用,然后在啟動創建新卷的容器時使用。
初始設置
此示例假定您有兩個節點,第一個節點是Docker主機,可以使用SSH連接到第二個節點。
在Docker主機上,安裝vieux/sshfs
插件:
[root@benjamincloud ~]# docker plugin install --grant-all-permissions vieux/sshfs latest: Pulling from vieux/sshfs 52d435ada6a4: Download complete Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811 Status: Downloaded newer image for vieux/sshfs:latest Installed plugin vieux/sshfs
使用卷驅動程序創建卷
此示例指定SSH密碼,但如果兩台主機配置了共享密鑰,則可以省略密碼。每個卷驅動程序可以具有零個或多個可配置選項,每個選項都使用-o
標志指定。
[root@benjamincloud ~]# docker volume create --driver vieux/sshfs -o sshcmd=test@node2:/home/test -o password=testpassword sshvolume
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
備份,還原或遷移數據卷
卷對備份,還原和遷移很有用。使用該 --volumes-from
標志創建一個安裝該卷的新容器
備份容器
例如,在下一個命令中,我們:
- 啟動新容器並從
dbstore
容器裝入卷 - 掛載本地主機目錄為
/backup
- 將/dbdata 目錄下的數據備份到 /backup/backup.tar。
[root@benjamincloud ~]# docker run -v /dbdata --name dbstore ubuntu [root@benjamincloud ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c4674f6fb834 ubuntu "/bin/bash" 10 seconds ago Exited (0) 9 seconds ago dbstore [root@benjamincloud ~]# docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata tar: Removing leading `/' from member names /dbdata/
容器 /dbdata 的數據被備份到 docker主機的當前目錄
從備份還原容器
使用剛剛創建的備份,您可以將其還原到同一容器或您在其他位置創建的另一個容器。
例如,創建一個名為的新容器dbstore2
:
[root@benjamincloud ~]# docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
然后解壓縮新容器的數據卷中的備份文件:
root@benjamincloud ~]# docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
--strip 命令脫掉外衣,去掉一些符號文件
刪除卷
刪除容器后,Docker數據卷仍然存在。要考慮兩種類型的卷:
- 例如,命名卷在容器外部具有特定的源表單
awesome:/bar
。 - 匿名卷沒有特定的源,因此在刪除容器時,指示Docker Engine守護進程刪除它們。
刪除匿名卷
要自動刪除匿名卷,請使用該--rm
選項。例如,此命令創建匿名/foo
卷。移除容器后,Docker Engine會刪除/foo
卷但不會刪除awesome
卷。
刪除所有卷
要刪除所有未使用的卷並釋放空間: