簡介 介紹 Docker的存儲捲稱之為volume,本質上容器上的一個或者多個目錄,而這些目錄繞過了聯合文件系統,與宿主機中的目錄或者其他容器目錄進行了綁定關係,這種綁定關係可以看作Linux的mount操作,當容器中的程式對這些目錄寫入數據時,其實寫入到的是與之綁定的宿主機目錄上,這樣就實現了數據 ...
簡介
介紹
Docker的存儲捲稱之為volume,本質上容器上的一個或者多個目錄,而這些目錄繞過了聯合文件系統,與宿主機中的目錄或者其他容器目錄進行了綁定關係,這種綁定關係可以看作Linux的mount操作,當容器中的程式對這些目錄寫入數據時,其實寫入到的是與之綁定的宿主機目錄上,這樣就實現了數據的存儲功能。特別說明:本文章所使用的docker版本基於v18.X,對於較早版本的docker並不適合,例如tmpfs類型捲是v17.06新加入的存儲捲。
作用
預設情況下,容器不使用任何 volume時,容器的數據被保存在容器之內,它只在容器的生命周期記憶體在,會隨著容器的刪除而被刪除,而想要持久化的存儲這些數據,就得使用存儲捲。特別的,保存容器中的數據也可以使用 docker commit 命令將容器提交為一個新的鏡像,這個鏡像中會保存容器運行時的所有數據(綁定的數據捲除外),但此種方法非常不推薦,因為這樣的鏡像通常會很大,鏡像拉取以及運行容器都會變慢。當容器使用了存儲捲,即使容器被刪除了,但是與綁定的存儲捲還在,對應目錄的數據都會保存,如果想要恢復該容器,只要新建的容器綁定該存儲捲,對應目錄的數據也會隨之恢復。
分類
Docker存儲捲可分為兩類:
- Volumes:數據捲,這類存儲捲是被Docker Daemon管理,可使用docker volume create顯示創建,被創建出來的捲位於/var/lib/docker/volumes/下,使用時候只需指定使用捲的名稱以及對應的容器的一個目錄,刪除時候只需指定刪除捲名即可,這類數據捲是存儲數據最為推薦的方式。
- Bind mounts :綁定掛載捲,從早版本docker提供,這類存儲捲可以是宿主機的任意目錄,也可以是來自其他容器的目錄,不受docker Daemon管理,刪除時候需要手動清理目錄。
- tmpfs mounts:臨時掛載捲,該類存儲捲數據存放在主機記憶體中,好處在於這類存儲捲由於使用的tmpfs格式文件系統,讀寫性能好,但同時也增加了主機的記憶體開銷,Docker早期版本不支持此類存儲捲。
以下是其示意圖:
存儲捲使用
--volume&&--mount
存儲捲的使用是在docker run命令時候使用-v或者--volume來指明使用的存儲捲,但是如果需要指明更多選項如捲類型、驅動等那就需要使用--mount來指明更多的選項。以下是兩種選擇的使用方法。
-v或--volume選項:[volume_name]:container_path:[options]
解釋:
由三個欄位組成,用冒號字元(:)分隔,欄位必須按正確的順序排列
volume_name:捲名,可省略,省略的時候預設會分配一個隨機目錄,在/var/lib/docker/volumes/隨機目錄/_data。還可以指定宿主機目錄。
container_path:綁定的容器中的目錄,必須。
options:其他選項,是逗號分隔的選項列表,例如讀寫模式(ro、rw),可省略。
示例:創建一個綁定掛載捲
--mount:該選項從V17.06加入,由多個鍵值對組成,用逗號分隔,每個鍵值由<key>=<value>組成。常用的key如下:
- type:指明捲的類型,三種類型之一bind、volume、tmpfs
- source:可簡寫為src,指定掛載來源通常是捲名稱,匿名捲時忽略該選項
- destination:可簡寫為dst或target,指定容器中的使用的目錄
- readonly:指定捲是否為只讀
- volume-opt:其他掛載選項可以多次使用,採用volume-opt=type=nfs
示例:將上述容器使用--mount啟動(這裡換一個名稱為nginx-c2):
使用建議:兩個命令能都實現數據捲的掛載,如果是老用戶可以繼續使用-v的方式來運行容器,如果是新用戶推薦使用--mount,這樣的語法比較簡介明瞭,比如人性化的各種選項src、type、dest,但是如果需要使用tmpfs類型的數據捲時候必須使用--mount。
使用Volumes
volume類型的數據捲是比較推薦方式,它是能被Docker 管理的捲, 使用流程是先創建捲,在使用-v或--mount進行掛載。如果在docker run時候不指定其宿主機目錄,則預設也屬於volumes類型,也受Docker管理。
創建捲
[root@app51 ~]# docker volume create data-vol data-vol [root@app51 ~]# docker volume inspect data-vol [ { "CreatedAt": "2019-02-28T17:39:36+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/data-vol/_data", "Name": "data-vol", "Options": {}, "Scope": "local" } ] [root@app51 ~]#
掛載捲並寫入數據
[root@app51 ~]# docker run -it --name bs1 -v data-vol:/data/tmp busybox:latest /bin/sh / # ls /data/tmp/ / # echo "hello world" > /data/tmp/index.html / #
在宿主機上查看:
創建捲是還可以指定其他,列如指定大小、uid等其他選項,這些選項都是mount命令的選項,捲的管理中會介紹:
[root@app51 ~]# docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 test-vol6 test-vol6 [root@app51 ~]# docker run -it --name bs6 -v test-vol6:/data/tmp busybox:latest /bin/sh / # ls /data tmp
上面的掛載命令使用等價--mount:
[root@app51 ~]# docker run -it --name bs7 --mount type=volume,src=test-vol6,dst=/data/tmp busybox:latest /bin/sh / #
容器內可以使用mount命令可以查看掛載點:
使用bind mounts
綁定掛載捲使用,無非指定宿主機的具體某個目錄,可以使用-v HOST_PATH:CONTAINER_PATH 也可以使用--mount type=bind,src=HOST_PATH,dst=CONTAINER_PATH。
示例:
[root@app51 ~]# docker run -it --name bind-vol -v "$(pwd)":/data busybox:latest /bin/sh / # ls /data Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar / #
等價於使用--mount:
[root@app51 ~]# docker run -it --name bind-vol-1 --mount type=bind,src="$(pwd)",dst=/data busybox:latest /bin/sh / # ls /data Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar / #
以只讀的方式掛載:
[root@app51 ~]# docker run -it --name bind-vol-2 --mount type=bind,src="$(pwd)",dst=/data,readonly busybox:latest /bin/sh / # ls /data/ Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar / # cd /data/ /data # touch 1.txt touch: 1.txt: Read-only file system /data #
查看捲(新開終端):
[root@app51 ~]# docker inspect bind-vol-2 "Mounts": [ { "Type": "bind", "Source": "/root", "Target": "/data", "ReadOnly": true } ],
使用tmpfs mounts
tmpfs類型的捲只適用於Linux系統,命令行中除了使用--mount指定外還可以使用--tmpfs指定其類型。特別註意的,與volume捲和綁定掛載捲相反,tmpfs掛載是臨時的,並且僅在主機記憶體中持久存在,當容器停止時,將刪除tmpfs掛載,並且不會保留寫在那裡的文件。
示例 使用--mount:
[root@app51 ~]# docker run -it --name tmpfs-c1 --mount type=tmpfs,dst=/app busybox:latest /bin/sh / # / # mount |grep /app tmpfs on /app type tmpfs (rw,nosuid,nodev,noexec,relatime)
等價於使用--tmpfs:
[root@app51 ~]# docker run -it --name tmpfs-c2 --tmpfs /app busybox:latest /bin/sh / # mount |grep /app tmpfs on /app type tmpfs (rw,nosuid,nodev,noexec,relatime) / #
查看掛載捲:
[root@app51 ~]# docker inspect tmpfs-c1 "Mounts": [ { "Type": "tmpfs", "Source": "", "Destination": "/app", "Mode": "", "RW": true, "Propagation": "" } ],
註意--mount選項還支持指定掛載目錄的大小和許可權,選項如下:
tmpfs-size | 設置tmpfs類型捲的大小,預設無限制(即由宿主機記憶體決定) |
tmpfs-mode | 設置tmpfs類型捲掛載的目錄許可權,如1770。預設1777 |
指定一個大小為50m,目錄選項為1770類似為tmpfs的存儲捲:
[root@app51 ~]# docker run -it --name tmpfs-c3 --mount type=tmpfs,dst=/data/tmp,tmpfs-mode=1770,tmpfs-size=50m busybox:latest /bin/sh / # / # / # mo modinfo modprobe more mount mountpoint / # mount |grep /data/tmp tmpfs on /data/tmp type tmpfs (rw,nosuid,nodev,noexec,relatime,size=51200k,mode=1770) / # ls /data/ -l total 0 drwxrwx--T 2 root root 40 Mar 1 01:47 tmp
查看其存儲捲信息:
[root@app51 ~]# docker inspect tmpfs-c3 "Mounts": [ { "Type": "tmpfs", "Source": "", "Destination": "/data/tmp", "Mode": "", "RW": true, "Propagation": "" } ],
使用容器數據捲
除了以上數據捲外,還可以直接使用容器中已經掛載的數據捲,使用--volumes-from指定,此時兩個容器的數據捲是共用的。從本質上來講,這兩數據捲共同掛載了宿主機上的同一個目錄。
示例:創建一個容器share-c1掛載當前目錄(確保不要退出)
[root@app51 ~]# docker run -it --name share-c1 -v $(pwd):/data busybox:latest /bin/sh / # ls /data/ Dockerfile a.txt anaconda-ks.cfg backup.tar dr.sh nat.sh nginx-bus.tar.gz nginx.tar / #
在運行一個容器掛載share-c1的捲:
[root@app51 ~]# docker run -it --name share-c2 --volumes-from share-c1 busybox:latest /bin/sh / # ls /data/ Dockerfile a.txt anaconda-ks.cfg backup.tar dr.sh nat.sh nginx-bus.tar.gz nginx.tar / #
存儲捲管理
docker存儲捲管理通過docker volume命令組實現,v18.09的命令集合如下:
1.創建存儲捲
docker volume create [OPTIONS] [VOLUME_NAME]
通常這樣創建的捲會保存在宿主機目錄/var/lib/docker/volumes/VOLUME_NAME/_data如果不指名 VOLUME則會創建匿名捲,方式等同於在docker run -v不指定宿主機目錄。
常用選項:
-o, --opt :指定存儲捲掛載選項。常用選項如下:
- type: 掛載文件系統類型,可以是tmpfs、brtfs、甚至是nfs。
- device:掛載的設備,
- o:mount命令掛載選項,其選項可參考這裡
示例一:創建一個普通的捲名稱為test-vol-1。
[root@app51 test-vol-1]# docker volume create test-vol-1 test-vol-1 [root@app51 test-vol-1]# ls /var/ adm/ crash/ empty/ gopher/ lib/ lock/ mail/ opt/ run/ tmp/ yp/ cache/ db/ games/ kerberos/ local/ log/ nis/ preserve/ spool/ .updated [root@app51 test-vol-1]# ls /var/lib/docker/volumes/test-vol-1/ -l 總用量 0 drwxr-xr-x 2 root root 6 3月 1 11:08 _data [root@app51 test-vol-1]#
示例二:創建一個tmpfs類型的存儲捲,名稱為test-vol-2
[root@app51 test-vol-1]# docker volume create --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 test-vol-2 test-vol-2 ###掛載test-vol-2 [root@app51 test-vol-1]# docker run -it --name bs-c10 -v test-vol-2:/data busybox:latest /bin/sh / # mount |grep /data tmpfs on /data type tmpfs (rw,relatime,size=102400k,uid=1000) / #
示例三:創建一個nfs類型的存儲捲,伺服器地址為10.1.210.52,許可權讀寫,目錄為/data/tmp,名稱為test-vol-3
[root@app51 test-vol-1]# docker volume create --opt type=nfs --opt o=addr=10.1.210.52,rw --opt device=:/data/tmp test-vol-3 test-vol-3
需要註意的是:創建的捲即使創建成功了但是掛載的時候很可能出錯,docker不會在創建捲時候檢查掛載選項是否符合要求。
2.查看存儲捲詳情
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
常用選項:
-f, --format :輸出格式,基於go模版
示例:
[root@app51 ~]# docker inspect test-vol-1 [ { "CreatedAt": "2019-03-01T11:08:00+08:00", "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/test-vol-1/_data", "Name": "test-vol-1", "Options": {}, "Scope": "local" } ]
使用-f:.代表以根開頭,Name是一級欄位。
[root@app51 ~]# docker inspect test-vol-1 -f {{.Name}} test-vol-1 [root@app51 ~]#
3.查看所有存儲捲
docker volume ls [OPTIONS]
常用選項:
-f, --filter 過濾具體存儲捲
示例:
[root@app51 ~]# docker volume ls DRIVER VOLUME NAME local test-vol-1 local test-vol-2 local test-vol-3 [root@app51 ~]#
過濾某個捲:
[root@app51 ~]# docker volume ls -f name=test-vol-1 DRIVER VOLUME NAME local test-vol-1
4.刪除一個或多個捲
docker volume rm [OPTIONS] VOLUME [VOLUME...]
常用選項:
-f, --force 強制刪除存儲捲,即使它還在被使用
[root@app51 ~]# docker volume ls DRIVER VOLUME NAME local test-vol-1 local test-vol-2 local test-vol-3 [root@app51 ~]# docker volume rm test-vol-3 test-vol-3 [root@app51 ~]# docker volume ls DRIVER VOLUME NAME local test-vol-1 local test-vol-2 [root@app51 ~]#
5.移除本地未使用的捲
docker volume prune [OPTIONS]
[root@app51 ~]# docker volume prune WARNING! This will remove all local volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: test-vol-1 Total reclaimed space: 0B [root@app51 ~]#
數據捲的備份與恢復
數據備份
容器中的數據捲備份有兩種方式,一是你可以直接備份與之對應的宿主機目錄,二則運行一個容器掛載有數據的容器將其備份到與之對應的宿主機目錄。這裡演示下第二種數據備份方法。
方法:
1.創建備份容器並掛載需要備份的目錄,同時掛載宿主機目錄進行備份任務。
2.運行備份指令並將備份數據放到掛載的宿主機目錄,以下示例為/backup,將數據備份在來/backup就等於備份在了宿主機的$(pwd)目錄下,也就是當前目錄。
新建一個數據容器並寫入數據:
[root@app51 ~]# docker run -it --name data-c1 -v /data busybox:latest /bin/sh / # cd /data/ /data # touch 1.txt /data # echo "hello world" > index.html /data # ls -l total 4 -rw-r--r-- 1 root root 0 Mar 1 07:40 1.txt -rw-r--r-- 1 root root 12 Mar 1 07:40 index.html /data #
創建備份容器同時掛載兩個目錄進行數據備份:
[root@app51 ~]# docker run --rm --volumes-from data-c1 -v $(pwd):/backup centos tar cvf /backup/backup.tar /data /data/ /data/1.txt /data/index.html tar: Removing leading `/' from member names
查看備份數據:
[root@app51 ~]# ls -l 總用量 220332 -rw-------. 1 root root 1258 1月 16 00:15 anaconda-ks.cfg -rw-r--r-- 1 root root 7 2月 27 10:25 a.txt -rw-r--r-- 1 root root 10240 3月 1 15:42 backup.tar -rw-r--r-- 1 root root 76 2月 27 19:14 Dockerfile -rw-r--r-- 1 root root 578 1月 16 10:41 dr.sh -rw-r--r-- 1 root root 559 1月 16 14:53 nat.sh -rw------- 1 root root 114356736 2月 24 10:56 nginx-bus.tar.gz -rw------- 1 root root 111224320 2月 23 19:18 nginx.tar [root@app51 ~]# tar tvf backup.tar drwxr-xr-x root/root 0 2019-03-01 15:40 data/ -rw-r--r-- root/root 0 2019-03-01 15:40 data/1.txt -rw-r--r-- root/root 12 2019-03-01 15:40 data/index.html
數據恢復
恢複數據的原理與備份類似,也是啟動一個容器共用需要備份的目錄,同時掛載宿主機的備份目錄,最後解壓數據到備份目錄中。為了演示數據恢復,我將上述容器 data-c1中的data目錄中文件全部刪除:
[root@app51 ~]# docker run -it --name data-c1 -v /data busybox:latest /bin/sh / # cd /data/ /data # rm -rf * /data #
創建一個恢復容器:
[root@app51 ~]# docker run --rm --volumes-from data-c1 -v $(pwd):/backup centos bash -c "cd / && tar xvf /backup/backup.tar" data/ data/1.txt data/index.html [root@app51 ~]#
再次查看data-c1容器數據:
/data # rm -rf data /data # /data # /data # /data # /data # ls -l total 4 -rw-r--r-- 1 root root 0 Mar 1 07:40 1.txt -rw-r--r-- 1 root root 12 Mar 1 07:40 index.html /data #