volumes是保存Docker容器生成和使用的數據的首選機制。bind mounts依賴於主機的目錄結構,而卷則完全由Docker管理。卷比bind mounts有幾個優點:
- volumes比bind mounts跟容易備份或遷移。
- 可以使用Docker API進行管理。
- volumes可以在Linux或Windows平臺的容器上工作。
- 可以在多個容器之間安全共享
- 允許將volumes存儲在遠程主機或是雲服務提供商。
volumes的生命週期在容器之外。
我的理解爲:
- 容器可以使用bind mount的方式將數據存儲在主機的文件系統中。
- 容器可以使用volume的方式將數據存儲在卷中,volume屬於Docker管理,volume的存儲最終還是在文件系統中。
- 容器可以使用tmpfs mount的方式將數據存放在內存中。
個人覺得volume就像是給bind mount模式起了個名字,並且作爲一個整體被Docker管理。
具體操作一下,卷的創建方式有很多種,比如直接使用:
docker volume create my-vol
或是在容器啓動時使用-v
docker run -d --name test01 -v my-vol2:/app nginx:latest
還可以使用–mount
docker run -d --name test02 --mount src=my-vol3,target=/app nginx:latest
這裏簡單解釋一下-v、-mount的參數含義。
-v 後面可以跟三個值,分別用“:”冒號隔開,當然–volume和-v是一樣的。
- 第一個值可選,是用來設值volume卷名的。
- 第二個值必填,設值容器內的掛載路徑。
- 第三個值可選,是一些volume的屬性設值,比如:ro(只讀)。
-mount 後跟若干個key=val,也就是鍵值對,用","逗號隔開。分別有如下一些key:
- type : 可選值有bind、volume、tmpfs,也就是設值卷的類型。
- source | src : 用來設值卷名。
- destination : 目的地,也就是容器內的掛載路徑。
- readonly : 設值卷的只讀屬性。
- volume-opt : 該參數可以有多個,值還是一個key=val,也就是像 volume-opt=key=val這樣子。用於設置其他屬性。
我們還可以使用:docker volume ls
查看列表,使用:docker inspect my-vol3
查看詳情。
[
{
"CreatedAt": "2018-11-22T04:22:37-05:00", # 卷的創建時間
"Driver": "local", # 卷的驅動
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/my-vol3/_data", # 卷在文件系統的存儲位置
"Name": "my-vol3", # 卷名
"Options": null,
"Scope": "local"
}
]
刪除volume:docker volume rm my-vol3
,這裏注意,刪除volume之前刪除使用了該volume的容器。
當然也可以在同主機中的容器之間共享volume,做個簡單的示例。
啓動倆個nginx容器,使用同一個volume,volume在容器中的掛載位置是:/usr/share/nginx/html
這個位置是Nginx默認存儲HTML的文件夾。
啓動第一個Nginx容器:
docker run -d --name nginx01 -p 10080:80 -v nginx-vol:/usr/share/nginx/html nginx:latest
啓動成功後我們到nginx-vol卷的目錄下修改index.html內容,刪除body中<h1>Welcome to nginx!</h1>
以外的全部內容,訪問Nginx首頁:
再啓動第二個容器:
docker run -d --name nginx02 -p 10081:80 -v nginx-vol:/usr/share/nginx/html nginx:latest
訪問首頁:
沒有修改第二個容器,它使用了我在第一個容器中修改後的首頁。
同主機下的容器共享volume實現還是比較簡單,接下來搞一下不同主機下的容器共享volume。
這裏需要改變volume driver了,不能使用之前的local。
官方文檔中的例子使用的是vieux/sshfs
,這裏先安裝一下插件
docker plugin install --grant-all-permissions vieux/sshfs
這裏我們啓動倆個機器,ip分別是:
- 192.168.1.164
- 192.168.1.130
前面的內容都是在192.168.1.164這臺主機上操作的,這裏我繼續使用之前創建的nginx01容器,啓動容器並查看一下容器的Mounts:
Source是nginx-vol卷在文件系統中的存儲位置,待會會用到。
切換到192.168.1.130主機,之前的插件只需要安裝在這臺主機上,同樣運行一個nginx容器,但這裏要使用vieux/sshfs
驅動創建卷:
docker run -d --name nginx-sshvol \
-p 10080:80 \
--mount src=sshvol,target=/usr/share/nginx/html,type=volume,volume-driver=vieux/sshfs,[email protected]:/var/lib/docker/volumes/nginx-vol/_data,volume-opt=password=**** \
nginx:latest
啓動成功後訪問192.168.1.130:10080,不出意外的話應該和之前一樣,頁面只有一個歡迎標題。可實際顯示的是403,Bug可能會遲到,但永遠不會缺席。
查看容器啓動日誌:
[root@localhost ~]# docker logs nginx-sshvol
192.168.1.157 - - [23/Nov/2018:02:29:17 +0000] "GET / HTTP/1.1" 403 571 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" "-"
2018/11/23 02:29:17 [error] 6#6: *1 "/usr/share/nginx/html/index.html" is forbidden (13: Permission denied), client: 192.168.1.157, server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.130:10080"
2018/11/23 02:29:17 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (13: Permission denied), client: 192.168.1.157, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.1.130:10080", referrer: "http://192.168.1.130:10080/"
192.168.1.157 - - [23/Nov/2018:02:29:17 +0000] "GET /favicon.ico HTTP/1.1" 403 571 "http://192.168.1.130:10080/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" "-"
這是一個很常見的Nginx權限不足問題,我們將nginx.conf配置中的user改爲root即可。由於容器中沒有vi命令,我們用docker cp
命令將nginx.conf複製到宿主機中,修改後同樣使用docker cp
再給它覆蓋回去。
複製配置到宿主機:docker cp nginx-sshvol:/etc/nginx/nginx.conf ./nginx.conf
覆蓋容器中的配置:docker cp ./nginx.conf nginx-sshvol:/etc/nginx/nginx.conf
覆蓋配置之後重啓容器,再次訪問,成功解決: