1. Docker数据卷
- Docker中的容器一旦删除,容器本身对应的rootfs文件系统就会被删除,容器中的所有数据也将随之删除。为此,Docker提供了数据卷(data volume),数据卷除了可以持久化数据,还可以用于容器间共享数据。
- 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过联合文件系统,被设计用来保存数据,而不管容器的生命周期。
- 数据卷可以在容器之间共享和重用。
- 当你删除一个容器时,Docker不会自动地删除一个数据卷。卷会一直存在,直到没有容器使用。
Docker有两个容器选项可以在主机中存储文件,为绑定挂载和docker管理卷,使用-v选项来创建或挂载一个数据卷并挂载到容器里。
绑定挂载 | docker管理卷 | |
volume位置 | 可任意指定 | 在/var/lib/docker/volume/...下 |
对已有mount point影响 | 隐藏并替换为volume | 原有数据复制到volume |
是否支持单个文件 | 支持 | 不支持,只能是目录 |
权限控制 | 可设置为只读,默认读写权限 | 无控制,均为读写权限 |
移植性 | 移植性若,与主机路径绑定 | 移植性强,无需指定主机目录 |
1.1 bind mount(绑定挂载)
- 绑定挂载是将主机上的目录或文件挂载到容器里。
- -v选项指定的路径如果不存在,挂载时会自动创建。
- 格式:-v=[host-dir]:[container-dir]:[rw|ro]。
- host-dir:表示宿主机上的目录,如果不存在,Docker会自动在宿主机上创建该目录。
- container-dir:表示容器内部对应的目录,如果该目录不存在,Docker也会在容器内部创建该目录。
- rw|ro:用于控制卷的读写权限。
可以挂载主机的目录到容器,作为容器的数据卷。
将主机上的/data目录挂载到容器中的/volume1。通过这种方式我们可以在主机与容器间进行数据交换。即使容器被删除,数据仍然会保存在主机上。实际上,Docker内部是通过mount --bind来实现的。
ycy@ubuntu18:~$ docker run -it --rm -v /data:/volume1 ubuntu
root@e1f6b98857fa:/# df -lh | grep volume1
/dev/sda1 49G 8.9G 38G 20% /volume1
root@e1f6b98857fa:/# ls /volume1/
index.html
root@e1f6b98857fa:/# echo 12345 > /volume1/a.txt
root@e1f6b98857fa:/# exit
exit
ycy@ubuntu18:~$ ls /data/
a.txt index.html
ycy@ubuntu18:~$ cat /data/a.txt
12345
也可以挂载主机上的文件作为容器的数据卷。主要用于在主机与容器之间共享配置文件。一般来说,应用程序不会变,而配置文件可能会经常变化,如果对每个配置文件都做成一个镜像,会造成镜像版本过多、管理不便、而且不够灵活。实际上,我们可以将配置文件放在主机上,然后挂载到容器,这样,就可以随时更改主机文件,容器内部看到的文件也会随之改变。
将主机上的/etc/hosts文件挂载到容器中的/etc/hosts下。
ycy@ubuntu18:~$ docker run -it --rm -v /etc/hosts:/etc/hosts ubuntu
root@c1455429f23a:/# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu18
root@c1455429f23a:/# echo "192.168.146.100 www.a.com" >> /etc/hosts
root@c1455429f23a:/# ycy@ubuntu18:~$
ycy@ubuntu18:~$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu18
192.168.146.100 www.a.com
1.2 docker managed volume(docker管理卷)
- docker管理卷不需要指定mount源,docker自动为容器创建数据卷目录
- 默认创建的数据卷目录都在/var/lib/docker/volumes中。
- 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中。
ycy@ubuntu18:~$ docker run -d --name s2 -v /volumes2 ubuntu
62a3530355cf0d3f7b5e5ffd025935d8e4d259db50929602b6cf5e274ab32432
ycy@ubuntu18:~$ docker inspect -f "{{ .Mounts }}" s2
[{volume 3e2cd447ec602fe271aedd4b266345f8c049279d66ecaa718b9f22509d505b05 /var/lib/docker/volumes/3e2cd447ec602fe271aedd4b266345f8c049279d66ecaa718b9f22509d505b05/_data /volumes2 local true }]
上面默认的文件名是以数据卷名命名的,可以自定义设置,如下。
ycy@ubuntu18:~$ docker run -d --name s3 -v s3:/volumes3 ubuntu
05591a7326637839aef35603915ee5f147f0ed4eb883701e5c418c6588940425
ycy@ubuntu18:~$ docker inspect -f "{{ .Mounts }}" s3
[{volume s3 /var/lib/docker/volumes/s3/_data /volumes3 local z true }]
2. 数据卷容器
数据卷容器,是专门为其他容器提供数据卷的容器。
创建一个命名的数据卷容器,供其他容器挂载。
ycy@ubuntu18:~$ docker run -d --name dbdata -v /dbdata ubuntu
e050b4a151c474348d35c923454352393327f386f3f86bd7f1c3b6fb86529976
使用docker inspect inspect命令验证创建卷并安装正确,寻找Mounts部分。
ycy@ubuntu18:~$ docker inspect -f "{{ .Mounts }}" dbdata
[{volume 4f5b5fb57ff9b662b16c748fbeb92ccb2174cd5dfa247c6b99a53be6f1aa48ee /var/lib/docker/volumes/4f5b5fb57ff9b662b16c748fbeb92ccb2174cd5dfa247c6b99a53be6f1aa48ee/_data /dbdata local true }]
在其他容器中使用--volumes-from来挂载指定容器中的数据卷。这样,db1和db2也可以看到/dbdata数据卷的内容。
ycy@ubuntu18:~$ docker run -d --name db1 --volumes-from dbdata ubuntu
7e7697abd99adfef4039f5b7b8250b0975da884f368759271a273801921871a6
ycy@ubuntu18:~$ docker run -d --name db2 --volumes-from dbdata ubuntu
d9eccd03f32dd9c4c9e4c555fb0e08629a745bc1d9db45cae7635368ca2c29f1
还可以同时使用多个--volumes-from参数,从多个容器挂载多个数据卷。也可以从其他已经挂载数据卷容器的容器(如db1/db2)挂载数据卷。
ycy@ubuntu18:~$ docker run -d --name db3 --volumes-from db1 ubuntu
5d9cad23e45c1330def992a5fa9b34bad7ac95cafced6679649774ae8b95811c
如果删除挂载了数据卷的容器(包括初始的databa容器和其他的db1/db2/db3容器),数据卷并不会被删除。如果想删除数据卷,必须在最后一个引用该数据卷的时候调用docker volume rm命令来删除数据卷,docker volume prune删除所有数据卷。
ycy@ubuntu18:~$ docker rm -f $(docker ps -a -q)
5d9cad23e45c
d9eccd03f32d
7e7697abd99a
e050b4a151c4
root@ubuntu18:~# ls /var/lib/docker/volumes/
4f5b5fb57ff9b662b16c748fbeb92ccb2174cd5dfa247c6b99a53be6f1aa48ee
metadata.db
s3
ycy@ubuntu18:~$ docker volume rm 4f5b5fb57ff9b662b16c748fbeb92ccb2174cd5dfa247c6b99a53be6f1aa48ee
4f5b5fb57ff9b662b16c748fbeb92ccb2174cd5dfa247c6b99a53be6f1aa48ee
3. 备份、恢复和迁移数据卷
3.1 备份数据卷
通过--volumes-from参数挂载数据卷,然后备份数据卷中的数据。
创建一个新的容器,将主机本地目录挂载的/backup,然后将数据卷容器dbdata的数据卷(/dbdata)打包到/backup/backup.tar。然后再主机的当前目录下就可以得到backup.tar。
ycy@ubuntu18:~$ docker run -d --name dbdata -v /dbdata ubuntu
f91c84972927905701d16110fa97d2f31cd273ce30219da93342573c1e1d07f1
ycy@ubuntu18:~$ docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar -cvf /backup/backup.tar /dbdata
/dbdata/
tar: Removing leading `/' from member names
ycy@ubuntu18:~$ ll -h backup.tar
-rw-r--r-- 1 root root 10K 9月 5 16:11 backup.tar
3.2 恢复数据卷
可以将备份的数据恢复到原有容器或者其他任何容器。比如将backup.tar的数据恢复到一个新的容器dbdata2.
ycy@ubuntu18:~$ docker run -v /dbdata --name dbdata2 ubuntu
然后创建另一个容器,挂载dbdata2的容器,并使用tar解压备份文件到挂载的容器卷中。
ycy@ubuntu18:~$ docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar -xvf /backup/backup.tar
dbdata/