Docker - Docker資料持久化
Docker的資料持久化主要有兩種方式:
- Bind Mount。
- Volume。
Docker的資料持久化,即是資料不随着容器的結束而結束,資料存儲于主控端上,要麼存儲于主控端某個指定目錄中(使用Bind Mount),要麼存儲于Docker管理的Volume中(
/var/lib/docker/volumes
下)。
Bind Mount在Docker早期便開始使用了,用于将主控端中的目錄挂載(
mount
)到容器中。但是當Bind Mount在不同的主控端系統時,它是不可移植的,比如Windows和Linux的目錄結構是不一樣的,Bind Mount所指向的主控端目錄也不能一樣。這也是為什麼Bind Mount不能出現在
Dockerfile
中的原因,因為這樣
Dockerfile
就不可移植了。
Bind Mount有幾點需要注意:
- 主控端的目錄路徑必須為全路徑(準确的說需要以
或/
開始的路徑),不然Docker會将其當做Volume而不是Bind Mount處理。~/
- 如果主控端上的目錄不存在,Docker會自動建立該目錄。
- 如果容器中的目錄不存在,Docker會自動建立該目錄。
- 主控端目錄無論有沒檔案,都會覆寫容器挂載的目錄。
Volume也是繞過容器的檔案系統,直接将資料存儲到主控端上,隻是Volume是被Docker管理的,Docker下所有的Volume都在主控端上的指定目錄下
/var/lib/docker/volumes
。
還有需要注意的是:
- Bind Mount:容器挂載的目錄以主控端目錄為準,無論主控端目錄有無檔案,都會覆寫容器挂載的目錄。
- Volume:主控端目錄有檔案時,以主控端目錄為準;主控端目錄沒有檔案時,從容器挂載的目錄複制過來,再以主控端目錄為準。
挂載資料卷(Volume)
在鏡像
centos:7
上建立容器,并且将容器命名為
centos.7.5
,通過
-v
選項可以給容器添加資料卷;啟動之後,到容器内部可以看到資料卷的
Destination
是
centos-volume
(由
-v
選項後面的參數指定),在
centos-volume
中建立檔案
hello_kaven
。
[root@izoq008ryseuupz docker]# docker run -it --name centos.7.5 -v centos-volume centos:7
[root@e2a5901b29b2 /]# ll
total 60
-rw-r--r-- 1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Nov 25 09:36 centos-volume
drwxr-xr-x 5 root root 360 Nov 25 09:36 dev
drwxr-xr-x 1 root root 4096 Nov 25 09:36 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 92 root root 0 Nov 25 09:36 proc
dr-xr-x--- 2 root root 4096 Nov 13 01:55 root
drwxr-xr-x 11 root root 4096 Nov 13 01:55 run
lrwxrwxrwx 1 root root 8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Apr 11 2018 sys
drwxrwxrwt 7 root root 4096 Nov 13 01:55 tmp
drwxr-xr-x 13 root root 4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root 4096 Nov 13 01:54 var
[root@e2a5901b29b2 /]# cd centos-volume
[root@e2a5901b29b2 centos-volume]# ll
total 0
[root@e2a5901b29b2 centos-volume]# echo "hello kaven" > hello_kaven
[root@e2a5901b29b2 centos-volume]# ll
total 4
-rw-r--r-- 1 root root 12 Nov 25 09:39 hello_kaven
[root@e2a5901b29b2 centos-volume]# cat hello_kaven
hello kaven
容器是否成功挂載到資料卷,可以通過檢視容器資訊來擷取,運作下面的指令即可。
docker inspect centos.7.5
得到的資訊中有下面這一段。
"Mounts": [
{
"Type": "volume",
"Name": "c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4",
"Source": "/var/lib/docker/volumes/c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4/_data",
"Destination": "centos-volume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
類型是
volume
,
/var/lib/docker/volumes/c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4/_data
就是資料卷在主控端中的目錄路徑,通過
docker volume ls
指令,也可以查詢到資料卷名稱為
c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4
的資料卷。
[root@izoq008ryseuupz docker]# docker volume ls
DRIVER VOLUME NAME
local 3c1ed533ce142b49eadc15ba57b87a3bac780e89e22c06503b3e909ab69ed62f
local 5b086d5fdb68b5a58593fdca6d6f0a9b3ead0ed929fd3961b7db48e3a928c24d
local 6b5a0394e690c4e0e869ddecc0db24a748a0229c70a83db46e0f2f95e3314958
local 8eb0f149b72711acd9618f827fc26a9afcce63ed51f1e60ac48e752344f88f22
local 08b4d10ef219075ee8a283112be06e1df52729bf23d3216342da3f8b21a0c127
local 31a6cbc600b3d30d0c567b3842ce5e7944495fcc12d42008385912d32facfd7a
local 208ddc66938b611237d4e868cb8800a36b5390969ba7a22d2d2e65a8c173b2c8
local 3285a7fb977eb7a87da83b2a5ff838c98037b15ec659eeff68c489e7004114ea
local a4beb8e0e17a3369c8c9a447d777323df71d2b5e2f77ebfc69cc99af39e1077a
local c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4
local centos-volume
local db153ec29b07b6268e7204fc2e91a32db91797bcd8f4d92c7e2637577cd1a155
local dcf0505225e08c4c4d24f0e89ac83ed02a5387620734c4add6ab4f1d8196489c
local f00edae7bd06b264a25329143fa2207e998491e459c24b0c30b1f78996a49369
[root@izoq008ryseuupz docker]# cd volumes
[root@izoq008ryseuupz volumes]# pwd
/var/lib/docker/volumes
[root@izoq008ryseuupz volumes]# cd c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4
[root@izoq008ryseuupz c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4]# ll
total 4
drwxr-xr-x 3 root root 4096 Nov 25 17:39 _data
[root@izoq008ryseuupz c8079a1f169f2f0d93923db7b785f1033a46bdc8cf6baf73d742ebbb3c03d6a4]# cd _data
[root@izoq008ryseuupz _data]# ll
total 4
-rw-r--r-- 1 root root 12 Nov 25 17:39 hello_kaven
[root@izoq008ryseuupz _data]# cat hello_kaven
hello kaven
很顯然,容器到主控端之間的資料共享已經實作了。那主控端到容器呢?當然也是可以的。
[root@izoq008ryseuupz _data]# echo "this is new file" > newFile
[root@izoq008ryseuupz _data]# ll
total 8
-rw-r--r-- 1 root root 12 Nov 25 17:39 hello_kaven
-rw-r--r-- 1 root root 17 Nov 25 18:08 newFile
[root@izoq008ryseuupz _data]# docker start -i centos.7.5
[root@e2a5901b29b2 /]# cd centos-volume
[root@e2a5901b29b2 centos-volume]# ll
total 8
-rw-r--r-- 1 root root 12 Nov 25 09:39 hello_kaven
-rw-r--r-- 1 root root 17 Nov 25 10:08 newFile
[root@e2a5901b29b2 centos-volume]# cat newFile
this is new file
Bind Mount
将容器目錄
/shared_volume
挂載到主控端目錄
/var/lib/docker/volumes/shared_volume
。
docker run -it --name centos.share1 -v /var/lib/docker/volumes/shared_volume:/shared_volume centos:7
在容器挂載目錄中建立檔案
share
,在主控端挂載目錄中也可以通路到。
[root@izoq008ryseuupz volume]# cd /var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# pwd
/var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.share1 -v /var/lib/docker/volumes/shared_volume:/shared_volume centos:7
[root@1065ceefb3da /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin shared_volume srv sys tmp usr var
[root@1065ceefb3da /]# cd shared_volume
[root@1065ceefb3da shared_volume]# echo "this is share" > share
[root@1065ceefb3da shared_volume]# ls
share
[root@1065ceefb3da shared_volume]# exit
exit
[root@izoq008ryseuupz shared_volume]# ls
share
[root@izoq008ryseuupz shared_volume]# cat share
this is share
當然反過來也可以。
[root@izoq008ryseuupz ~]# cd /var/lib/docker/volumes/shared_volume
[root@izoq008ryseuupz shared_volume]# ll
total 4
-rw-r--r-- 1 root root 14 Nov 25 21:19 share
[root@izoq008ryseuupz shared_volume]# mkdir share2
[root@izoq008ryseuupz shared_volume]# ll
total 8
-rw-r--r-- 1 root root 14 Nov 25 21:19 share
drwxr-xr-x 2 root root 4096 Nov 27 12:26 share2
[root@izoq008ryseuupz shared_volume]# docker start -i centos.share1
[root@1065ceefb3da /]# cd shared_volume
[root@1065ceefb3da shared_volume]# ll
total 8
-rw-r--r-- 1 root root 14 Nov 25 13:19 share
drwxr-xr-x 2 root root 4096 Nov 27 04:26 share2
檢視容器資訊。
docker inspect centos.share1
通過下面的資訊可以知道容器已經成功挂載了主控端目錄。
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/docker/volumes/shared_volume",
"Destination": "/shared_volume",
"Mode": "",
"RW": true,
"Propagation": "rslave"
}
]
類型是
bind
。
挂載指定資料卷(Volume)
不需要自己去建立資料卷,通過下面這條指令可以讓Docker去建立資料卷
kaven_volume
。
docker run -itd --name kaven -v kaven_volume:/kaven/volume centos:7
容器
kaven
成功運作起來了。
[root@izoq008ryseuupz ~]# docker run -itd --name kaven -v kaven_volume:/kaven/volume centos:7
97bff81a64bfd63d12e931705ae3bbb8266f6f53a8612fe965f37e0ce53d6c96
[root@izoq008ryseuupz ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97bff81a64bf centos:7 "/bin/bash" 3 seconds ago Up 3 seconds kaven
檢視容器資訊。
docker inspect kaven
通過下面的資訊可以知道容器已經成功挂載了資料卷。
"Mounts": [
{
"Type": "volume",
"Name": "kaven_volume",
"Source": "/var/lib/docker/volumes/kaven_volume/_data",
"Destination": "/kaven/volume",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
類型是
volume
。
挂載其他容器的資料卷
比如挂載容器
kaven
的資料卷。
docker inspect kaven
"Mounts": [
{
"Type": "volume",
"Name": "kaven_volume",
"Source": "/var/lib/docker/volumes/kaven_volume/_data",
"Destination": "/kaven/volume",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]
通過
docker run
指令的
--volumes-from
選項,可以讓容器挂載其他容器的資料卷。
docker run -it --name centos.kaven --volumes-from kaven centos:7
[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.kaven --volumes-from kaven centos:7
[root@5fc01525a699 /]# ll
total 60
-rw-r--r-- 1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x 5 root root 360 Nov 27 04:33 dev
drwxr-xr-x 1 root root 4096 Nov 27 04:33 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
drwxr-xr-x 3 root root 4096 Nov 27 04:33 kaven
lrwxrwxrwx 1 root root 7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 104 root root 0 Nov 27 04:33 proc
dr-xr-x--- 2 root root 4096 Nov 13 01:55 root
drwxr-xr-x 11 root root 4096 Nov 13 01:55 run
lrwxrwxrwx 1 root root 8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Apr 11 2018 sys
drwxrwxrwt 7 root root 4096 Nov 13 01:55 tmp
drwxr-xr-x 13 root root 4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root 4096 Nov 13 01:54 var
[root@5fc01525a699 /]# cd kaven
[root@5fc01525a699 kaven]# ll
total 4
drwxr-xr-x 2 root root 4096 Nov 27 01:24 volume
[root@5fc01525a699 kaven]# cd volume
[root@5fc01525a699 volume]# ll
total 0
[root@5fc01525a699 volume]# exit
exit
成功挂載了容器
kaven
的資料卷。
docker inspect centos.kaven
"Mounts": [
{
"Type": "volume",
"Name": "kaven_volume",
"Source": "/var/lib/docker/volumes/kaven_volume/_data",
"Destination": "/kaven/volume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
類型也是
volume
。
挂載多個資料卷
可以通過多個
-v
選項來給容器挂載多個資料卷。
[root@izoq008ryseuupz ~]# docker run -it --name centos.kaven.blog -v one -v two centos:7
[root@7a2ff8ab22f8 /]# ll
total 64
-rw-r--r-- 1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x 5 root root 360 Nov 25 11:36 dev
drwxr-xr-x 1 root root 4096 Nov 25 11:36 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Nov 25 11:36 one
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 96 root root 0 Nov 25 11:36 proc
dr-xr-x--- 2 root root 4096 Nov 13 01:55 root
drwxr-xr-x 11 root root 4096 Nov 13 01:55 run
lrwxrwxrwx 1 root root 8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Apr 11 2018 sys
drwxrwxrwt 7 root root 4096 Nov 13 01:55 tmp
drwxr-xr-x 2 root root 4096 Nov 25 11:36 two
drwxr-xr-x 13 root root 4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root 4096 Nov 13 01:54 var
通過查詢容器資訊,可以知道多個資料卷是否全部挂載成功。
docker inspect centos.kaven.blog
"Mounts": [
{
"Type": "volume",
"Name": "a64fce3680730956d0f0935ef1b5e3695ca5605ef1c6d621cdc6f5d26636bca2",
"Source": "/var/lib/docker/volumes/a64fce3680730956d0f0935ef1b5e3695ca5605ef1c6d621cdc6f5d26636bca2/_data",
"Destination": "one",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "6960782eb9ef3472bbce7489f6371fb72c6c0c4107baaf79042ef33dc91fe0f1",
"Source": "/var/lib/docker/volumes/6960782eb9ef3472bbce7489f6371fb72c6c0c4107baaf79042ef33dc91fe0f1/_data",
"Destination": "two",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
類型也都是
volume
。
很顯然都挂載成功了。
資料卷隻讀權限
通過
:ro
可以讓容器對資料卷的權限變成隻讀。
docker run -it --name centos.ro -v volume_ro:/volume_ro_kaven:ro centos:7
可以看到在容器中不能在隻讀權限資料卷挂載的目錄中建立檔案夾(其他任何寫操作也不可以)。
[root@izoq008ryseuupz shared_volume]# docker run -it --name centos.ro -v volume_ro:/volume_ro_kaven:ro centos:7
[root@3a9b0efd3732 /]# ll
total 60
-rw-r--r-- 1 root root 12114 Nov 13 01:55 anaconda-post.log
lrwxrwxrwx 1 root root 7 Nov 13 01:53 bin -> usr/bin
drwxr-xr-x 5 root root 360 Nov 27 04:41 dev
drwxr-xr-x 1 root root 4096 Nov 27 04:41 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Nov 13 01:53 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 13 01:53 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 106 root root 0 Nov 27 04:41 proc
dr-xr-x--- 2 root root 4096 Nov 13 01:55 root
drwxr-xr-x 11 root root 4096 Nov 13 01:55 run
lrwxrwxrwx 1 root root 8 Nov 13 01:53 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Apr 11 2018 sys
drwxrwxrwt 7 root root 4096 Nov 13 01:55 tmp
drwxr-xr-x 13 root root 4096 Nov 13 01:53 usr
drwxr-xr-x 18 root root 4096 Nov 13 01:54 var
drwxr-xr-x 2 root root 4096 Nov 27 04:41 volume_ro_kaven
[root@3a9b0efd3732 /]# cd volume_ro_kaven
[root@3a9b0efd3732 volume_ro_kaven]# mkdir kaven
mkdir: cannot create directory 'kaven': Read-only file system
[root@3a9b0efd3732 volume_ro_kaven]# exit
exit
[root@izoq008ryseuupz shared_volume]# cd /var/lib/docker/volumes/volume_ro/_data
[root@izoq008ryseuupz _data]# mkdir kaven
[root@izoq008ryseuupz _data]# docker start -i centos.ro
[root@3a9b0efd3732 /]# cd volume_ro_kaven
[root@3a9b0efd3732 volume_ro_kaven]# ll
total 4
drwxr-xr-x 2 root root 4096 Nov 27 04:44 kaven
通過下面這條指令可以查詢到資料卷的挂載情況。
docker inspect centos.ro
"Mounts": [
{
"Type": "volume",
"Name": "volume_ro",
"Source": "/var/lib/docker/volumes/volume_ro/_data",
"Destination": "/volume_ro_kaven",
"Driver": "local",
"Mode": "ro",
"RW": false,
"Propagation": ""
}
]
類型也是
volume
,主控端中的目錄路徑
"Source": "/var/lib/docker/volumes/volume_ro/_data"
,容器中的目錄路徑
"Destination": "/volume_ro_kaven"
,并且通過
"RW": false
、
"Mode": "ro"
這些資訊,說明資料卷隻讀權限設定成功了。
這些挂載資料卷的方法,對Bind Mount方式進行Docker資料持久化也适用,這裡就不介紹了。