Docker提供了三種不一樣的方式用於將宿主的數據掛載到容器中:volumes,bind mounts,tmpfs volumes。當你不知道該選擇哪一種方式時,記住,volumes老是正確的選擇。html
不管選擇哪一種掛載方式,在容器內部看來,數據就是數據,並無什麼不一樣。主機的數據在容器的文件系統中總被顯示爲目錄或文件。如何簡單的理解這三種掛載方式的不一樣之處呢,咱們能夠理解爲在這三種方式下,容器內的數據在宿主機中存放的位置不一樣,見下圖:
- 若是你使用volumes的方式掛載了一個空的volume到某個容器的一個非空目錄中,則這個非空目錄中已存在的內容會被拷貝到這個volume中。相似的,若是在啓動容器時指定了一個不存在的volume,一個空的volume會被自動建立;
- 若是使用bind mounts的方式掛載,或者用volumes的方式掛載了一個非空的volume到容器的一個非空目錄中,則容器中這個非空目錄下的內容將暫時被掛載過來的volume中的內容所覆蓋(並未被刪除),當取消掛載後,容器中那個非空目錄中的文件仍然存在。就像在linux下的/mnt目錄下若是存在一些文件,在把USB掛載到/mnt時,在/mnt下就只能看到USB中的內容而看不見原先的文件,當取消USB掛載後,再進入/mnt就能夠看見原先的文件了。
選擇使用 -v仍是--mount
起初,-v或者--volume用於獨立容器,--mount用於swarm services。然而,從Docker 17.06開始,也但是使用--mount用於獨立容器。—mount命令更精準詳細。-v將選項進行了合併。使用--mount。
若是你須要制定volume驅動選項,你必須使用 --mount。
- -v或者--volume:由3部分參數組成,使用「:」間隔。順序不能顛倒。
- 第一個部分是volumes名字,在宿主機上具備惟一性。匿名卷名字系統給出。
- 第二部分是掛載到容器裏的文件或文件夾路徑。
- 第三部分是可選項列表分隔符,例如「or」,這些可選項在下面會討論。
- —mount:由多個鍵值對組成,<key>=<value>。—mount要比-v或者--volume命令更長,可是更容易理解。
- type,能夠是bind,volume或者tmpfs。這篇文章主要討論volumes,因此type一直使用volume.
- source,volumes的名字,匿名volume能夠省略。source可縮寫爲src.
- destination,掛載到容器中的文件或目錄路徑。可也縮寫爲dst或者使用target。
- readonly,指定掛載在容器中爲只讀。
- volume-opt,可選屬性,能夠屢次使用。
-v和--mount的不一樣行爲
與bind mounts不一樣,對於—mount和-v全部的選項均可以使用。
當使用volumes服務時,只支持--mount.
建立和管理volumes
不像bind mount,你能夠在容器外建立和管理volumes。
建立一個volume:
$ docker volume create my-vol
顯示全部volumes
$ docker volume ls
local my-vol
查看volumes
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
刪除一個volume:
$ docker volume rm my-vol
啓動一個帶volume的容器
若是你啓動一個帶有volume容器,volume尚未建立,Docker會爲你建立。下面的例子掛載myvol2到容器中的/app/下。
下面的例子-v和—mount結果是同樣的。
--mount:
$ docker run -d \
--name devtest \
--mount source=myvol2,target=/app \
nginx:latest
-v:
$ docker run -d \
--name devtest \
-v myvol2:/app \
nginx:latest
使用inspect查看掛載是否正確,查看Mounts部分:
"Mounts": [
{
"Type": "volume",
"Name": "myvol2",
"Source": "/var/lib/docker/volumes/myvol2/_data",
"Destination": "/app",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
能夠看出掛載正確,而且是可讀寫的。
中止容器而後刪除volume
$ docker container stop devtest
$ docker container rm devtest
$ docker volume rm myvol2
啓動一個帶有volumes服務
當你啓動服務定義一個volume,每一個服務可使用本身本地人volume.若是你使用local volume,容器不能分享數據,可是一些volume驅動支持分享存儲。Docker for AWS and Docker for Azure使用Cloudstor插件都支持持久化存儲。
下面的例子啓動4份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 moby Running Running 14 seconds ago
刪除服務
$ docker service rm devtest-service
服務標識的不一樣
docker service create 命令不支持-v或者—volume。必須使用—mount。
使用容器加載一個volume
和上面同樣,若是你啓動一個容器建立一個新的volume,在容器被掛載的目錄(/app/)中有文件或者文件夾,這個目錄中的內容會被拷貝到volume中。而後容器掛載使用volume,其餘容器使用這個volume也能夠訪問預加載內容。
爲了說明這個,這個例子啓動一個nginx容器而且加載一個新volume nginx-vol,裏面包括容器中/usr/share/nginx/html 目錄中的內容,裏面存儲的是nginx默認的HTML內容。
--mount and -v具備相同結果
--mount:
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html \
nginx:latest
-v
$ 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
使用只讀volume
對於一些開發應用,容器須要回寫數據到Docker主機。但有時容器只須要讀數據。請記住多個容器能夠掛載相同volume,一個掛載讀寫容器,也能夠掛載只讀容器,還能夠兩種同時掛載。
這個例子修改上面的例子,可是掛載的是隻讀容器,使用’or’分隔符處理選項列表,
--mount and -v具備相同結果
--mount
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
nginx:latest
-v
$ 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)的volume。
Volume驅動容許你在應用中抽象下層的存儲系統。例如,若是你的服務使用NFS驅動volume,你可使用不一樣的驅動更新服務,就像存儲在雲中的數據,不須要修改應用邏輯。
使用volume驅動
當你使用docker volume create建立一個volume,或者當你啓動一個帶有沒建立volume的容器,你能夠指定volume驅動。下面例子使用vieux/sshfs volume驅動 ,首先建立一個獨立的volume,而後啓動一個建立新volume的容器。
初始化設置
這個例子假設你有兩個節點,第一個是Docker主機並且能夠鏈接到第二個的ssh.
在Docker主機中安裝vieux/sshfs插件:
$ docker plugin install --grant-all-permissions vieux/sshfs
使用volume驅動建立volume
這個樣例指定一個SSH密碼,可是若是兩個主機共享keys配置,你能夠省略密碼。每一個volume驅動能夠沒有或者更多配置選項,可使用-o標識。
$ docker volume create --driver vieux/sshfs \
-o sshcmd=test@node2:/home/test \
-o password=testpassword \
sshvolume
test@node2:/home/test 爲遠程主機掛載點
啓動一個帶有使用volume驅動建立volume的容器
這個樣例指定一個SSH密碼,可是若是兩個主機共享keys配置,你能夠省略密碼。每一個volume驅動能夠沒有或者更多配置選項。若是volume驅動要穿可選參數,你必須使用—mount。
$ 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