1 Docker数据卷
前言:
- Docker镜像是由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
- 如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制。
- 关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失。
存在的问题:
- 存储于联合文件系统中,不易于宿主机访问;
- 容器间数据共享不方便。
- 删除容器其数据会丢失
- “卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定(关联)”
- “卷”的初衷是独立于容器的生命周期实现数据持久化。因此删除容器之时既不会删除卷,也不会对哪怕未被引用的卷做垃圾回收操作。
Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同。
1. Docker管理卷
docker run -it -v HOSTDIR:VOLUMEDIR --name bbox2 busybox
docker inspect -f {{.Mounts}} bbox2
2. 绑定挂载卷
docker run -it -name bbox1 -v /data busybox
docker inspect -f {{.Mounts}} bbox1
1.1 Docker管理的卷
需要打开两个终端来测试,终端1
[root@docker-node1 ~]# docker run --name b2 -it -v /data busybox:latest
/ # ls
bin data dev etc home proc root sys tmp usr var
/ # ls -l data
total 0
切换终端2,找到mounts对应的目录
[root@docker-node1 ~]# docker inspect b2
......
"Mounts": [
{
"Type": "volume",
"Name": "ec54c347d920dcc7183d7e6b4235c086b603bab2c58146472e187ad6d6bd126c", #<==UUID名称
"Source": "/var/lib/docker/volumes/ec54c347d920dcc7183d7e6b4235c086b603bab2c58146472e187ad6d6bd126c/_data", #<==这个是宿主机目录
"Destination": "/data", #<==这个是容器内的目录
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
......
[root@docker-node1 ~]# cd /var/lib/docker/volumes/ec54c347d920dcc7183d7e6b4235c086b603bab2c58146472e187ad6d6bd126c/_data/
[root@docker-node1 _data]# touch index.html
切换终端1
/ # ls -l data
total 0
-rw-r--r-- 1 root root 0 Nov 14 08:30 index.html
/ # echo "hello world" >data/index.html
/ # cat data/index.html
hello world
切换终端2
[root@docker-node1 _data]# cat index.html
hello world
1.2 绑定挂载卷(共享卷)
终端1
[root@docker-node1 ~]# docker run --name b2 -it --rm -v /data/volumes/b2:/data busybox:latest
/ # ls
bin data dev etc home proc root sys tmp usr var
切换到终端2
[root@docker-node1 ~]# docker inspect b2
......
"Mounts": [
{
"Type": "bind",
"Source": "/data/volumes/b2",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
......
[root@docker-node1 ~]# ll /data/volumes/b2/ # 宿主机会自动创建
total 0
[root@docker-node1 ~]# cd /data/volumes/b2/
[root@docker-node1 b2]# echo "busybox" >test.txt
[root@docker-node1 b2]# cat test.txt
busybox
切换到终端1
/ # cd data/
/data # ls
test.txt
/data # cat test.txt
busybox
这种支持持久化
退出b2,然后重新创建b2,这次换个容器目录
[root@docker-node1 ~]# docker run --name b2 -it --rm -v /data/volumes/b2:/data/web/html busybox:latest
/ # cat /data/web/html/test.txt
busybox
Tips:快速查找定位信息
[root@docker-node1 ~]# docker inspect -f {{.Mounts}} b2
[{bind /data/volumes/b2 /data/web/html true rprivate}]
[root@docker-node1 ~]# docker inspect -f {{.NetworkSettings.IPAddress}} b2
172.17.0.2
[root@docker-node1 ~]# docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
使不同容器共享宿主机同一个卷
再创建一个容器,绑定和b2同一个的卷
[root@docker-node1 ~]# docker run --name b3 -it --rm -v /data/volumes/b2/:/data/ busybox:latest
/ # ls /data/
test.txt
/ # echo "This is b3 Container" >> /data/test.txt
/ # cat /data/test.txt
busybox
This is b3 Container
切换到b2查看
/ # cat /data/web/html/test.txt
busybox
This is b3 Container
docker支持复制别的容器的存储卷
- 可以创建一个模板,专供别的容器来复制存储卷的位置或网络等信息
多个容器的卷使用同一个主机目录,如
docker run -it --name c1 -v /dacker/volumes/v1:/data busybox
docker run -it --name c2 -v /dacker/volumes/v2:/data busybox
复制使用其它容器的卷,为docker run命令使用–volumes-from选项
docker run -it --name bbox1 -v /docker/volumes/v1:/data busybox
docker run -it --name bbox2 --volumes-from bbox1 busybox
终端1,开启一个模板容器
[root@docker-node1 ~]# docker run --name infracon -it -v /data/infracon/volume/:/data/web/html busybox
/ #
终端2,创建一个新容器,复制模板的volume,若使用–network则会把模板的网络也复制过来
[root@docker-node1 ~]# docker run --name nginx --network container:infracon --volumes-from infracon -it busybox
/ #
终端3,查看两个容器的inspect信息
[root@docker-node1 ~]# docker inspect infracon
"Mounts": [
{
"Type": "bind",
"Source": "/data/infracon/volume",
"Destination": "/data/web/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"IPAddress": "172.17.0.2",
[root@docker-node1 ~]# docker inspect nginx
"Mounts": [
{
"Type": "bind",
"Source": "/data/infracon/volume",
"Destination": "/data/web/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"IPAddress": "",
可以发现复制volume的容器nginx inspect不能查到IP地址,但显示不出来并不是没有IP地址,去nginx容器上查看IP地址
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
END!