容器存储
目录:
容器存储
容器存储分为两种
- storage driver管理的镜像层和容器层
- Data Volume数据卷
storage driver
镜像分层
容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是 Copy-on-Write:
- 新数据会直接存放在最上面的容器层。
- 修改现有数据会先从镜像层将数据复制到容器层,修改后的数据直接保存在容器层中,镜像层保持不变。
- 如果多个层中有命名相同的文件,用户只能看到最上面那层中的文件。
分层结构使镜像和容器的创建、共享以及分发变得非常高效,而这些都要归功于 Docker storage driver。正是 storage driver 实现了多层数据的堆叠并为用户提供一个单一的合并之后的统一视图。
Docker 支持多种 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。对于 Docker 用户来说,具体选择使用哪个 storage driver 是一个难题,因为:
- 没有哪个driver能够适应所有的场景。
- driver本身在快速发展和迭代。
Docker优先使用Linux发行版默认的storage driver,Docker安装时会根据当前系统的配置选择默认的driver。默 driver具有最好的稳定性,因为默认driver在发行版上经过了严格的测试。
$ docker info | grep 'Storage Driver'
Storage Driver: overlay2
各层数据存放在/var/lib/docker/overlay2/
Data Volume
Data Volume和数据层的应用场景
- Database 软件 vs Database 数据
- Web 应用 vs 应用产生的日志
- 数据分析软件 vs input/output 数据
有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据,也就是说,这类容器是有状态的。
Data Volume的特点
- Data Volume是目录或文件,而非没有格式化的磁盘(块设备)
- 容器可以读写volume中的数据
- volume数据可以被永久的保存,即使使用它的容器已经销毁
bind mount
将主机上已存在的目录或文件挂载到容器,通过-v
的参数,格式为<host path>:<container path>
$ mkdir htdocs
$ echo testfile > htdocs/index.html
$ docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
40799eaff89805f66bf3eb8014965c34b0f9f8207a2906380e4358cf5a8a3dfc
$ curl 127.0.0.1:80
testfile
/usr/local/apache2/htdocs是httpd镜像存放静态文件的地方,由于/usr/local/apache2/htdocs已经存在,原来的数据被隐藏,取而代之是挂载的目录,和linux的mount命令是一致的。
更新一下主机上的文件
$ echo change > htdocs/index.html
$ curl 127.0.0.1:80
change
销毁容器
$ docker stop 40799eaff89805f66bf3eb8014965c34b0f9f8207a2906380e4358cf5a8a3dfc
40799eaff89805f66bf3eb8014965c34b0f9f8207a2906380e4358cf5a8a3dfc
$ docker rm 40799eaff89805f66bf3eb8014965c34b0f9f8207a2906380e4358cf5a8a3dfc
40799eaff89805f66bf3eb8014965c34b0f9f8207a2906380e4358cf5a8a3dfc
[root@VM_146_207_centos ~]# cat htdocs/index.html
change
容器没有本机数据依然正常
bind的时候默认容器是可写可读bind的目录下文件,可以通过一下方式进行只读操作
docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro httpd
这样bind有一些局限性就是需要考虑主机的一些目录结构
docker managed volume
$ docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
26f042d2779e9ef5940a0036c3df3cb017e5c2e30a8a01a83da771d81a74e803
$ docker inspect 26f042d2779e9ef5940a0036c3df3cb017e5c2e30a8a01a83da771d81a74e803
...
"Mounts": [
{
"Type": "volume",
"Name": "ada1620ee7c986b5d17fc16ba4aecf3fa55ca9693964eae2345cda74bb670cfe",
"Source": "/var/lib/docker/volumes/ada1620ee7c986b5d17fc16ba4aecf3fa55ca9693964eae2345cda74bb670cfe/_data",
"Destination": "/usr/local/apache2/htdocs",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
当然也可以看到docker volume inspect 26f042d2779e9ef5940a0036c3df3cb017e5c2e30a8a01a83da771d81a74e803
可以看到在启动容器后在/var/lib/docker/volumes/目录生成了一个目录
$ cat /var/lib/docker/volumes/ada1620ee7c986b5d17fc16ba4aecf3fa55ca9693964eae2345cda74bb670cfe/_data/index.html
<html><body><h1>It works!</h1></body></html>
数据和容器中的完全一致,是因为对原有目录或文件数据会拷贝的volume,这样数据依然是data volume管理数据,而不是storage driver
两个的区别
区别 | bind mount | managed volume |
---|---|---|
volume位置 | 任意指定 | /var/lib/docker/volumes/ |
对已有mount point的影响 | 隐藏并替换 | 将原有数据复制到volume |
是否支持单个文件 | 支持 | 不支持 |
权限控制 | 默认为读写,可设置为只读 | 无控制,均为只读 |
容器数据共享
volume container
docker create创建一个只提供数据的容器,不需要运行
$ docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other busybox
a817043acb216c6786c5b4402944041a9776ac343607e07a4026e19de0f7b57b
$ docker inspect vc_data
"Mounts": [
{
"Type": "bind",
"Source": "/root/htdocs",
"Destination": "/usr/local/apache2/htdocs",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "volume",
"Name": "4dd49c4339df779f42cb3c36db287c5da8b40f679387868cd82c73a4420286f0",
"Source": "/var/lib/docker/volumes/4dd49c4339df779f42cb3c36db287c5da8b40f679387868cd82c73a4420286f0/_data",
"Destination": "/other",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
$ docker run --name web-01 -d -p 80 --volumes-from vc_data httpd
c0e37573f51dd7d8886cdc9ce11b9ee804f49a9aeec541bdc176b6e58db57542
$ docker run --name web-02 -d -p 80 --volumes-from vc_data httpd
ff955643844a9b3cebb86757f66257e2fa9faf7d0064b5b37bf7bc97231eef9f
查看以容器为volume的信息
$ docker inspect ff955643844a9b3cebb86757f66257e2fa9faf7d0064b5b37bf7bc97231eef9f
"Mounts": [
{
"Type": "bind",
"Source": "/root/htdocs",
"Destination": "/usr/local/apache2/htdocs",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "volume",
"Name": "4dd49c4339df779f42cb3c36db287c5da8b40f679387868cd82c73a4420286f0",
"Source": "/var/lib/docker/volumes/4dd49c4339df779f42cb3c36db287c5da8b40f679387868cd82c73a4420286f0/_data",
"Destination": "/other",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
可以看到和原来的endpoint都一样
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff955643844a httpd "httpd-foreground" 10 minutes ago Up 10 minutes 0.0.0.0:32770->80/tcp web-02
c0e37573f51d httpd "httpd-foreground" 10 minutes ago Up 10 minutes 0.0.0.0:32769->80/tcp web-01
a817043acb21 busybox "sh" 39 minutes ago Created vc_data
$ curl 0.0.0.0:32770
change
$ curl 0.0.0.0:32769
change
$ echo change2 > htdocs/index.html
$ curl 0.0.0.0:32770
change2
$ curl 0.0.0.0:32769
change2
测试了一下修改也是可以共享存储
volume container
的容器和mount point
是一致的,有利于配置的规范和标准化,但也带来一定的局限
data-packed volume container
将数据打包进容器
Dockerfile
FROM busybox
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs
VOLUME的作用与-v
等效,用来创建docker managed volume
,mount point
为/usr/local/apache2/htdocs
构建镜像
docker build -t datapacked .
Sending build context to Docker daemon 32.77kB
Step 1/3 : FROM busybox
---> 59788edf1f3e
Step 2/3 : ADD htdocs /usr/local/apache2/htdocs
---> 851f80870f62
Step 3/3 : VOLUME /usr/local/apache2/htdocs
---> Running in d331b29e9958
Removing intermediate container d331b29e9958
---> c9baf47f1acc
Successfully built c9baf47f1acc
Successfully tagged datapacked:latest
创建volume container
$ docker create --name vc_data datapacked
115d3ab27af31a132cb1292ee89409764c6f7622a2a10f98d81e0778d9affa52
启动容器使用心得volume
$ docker run --name web -d -p 80:80 --volumes-from vc_data httpd
7057e2014b3d635b6101691f7bc6abbc1107b3ca5ab802886d6ea3fb4acb86c0
$ curl 127.0.0.1
change2
data-packed volume container
是自包含的,不依赖host
提供数据,具有很强的移植性,非常适合只使用静态数据的场景,比如应用的配置信息、web server的静态文件等
备份
直接备份本地挂载点数据即可
恢复
将备份数据拷贝到挂载点
迁移
数据和容器一起拷贝并启动
销毁
- docker不会销毁
bind mount
,需要在主机进行删除 docker managed volume
,在执行docker rm
删除容器时可以带上-v
参数,docker会将容器使用到的volume一并删除,但前提是没有其他容器mount该volume
$ docker volume ls
DRIVER VOLUME NAME
$ docker run --name bbox -v /test/data busybox
$ docker volume ls
DRIVER VOLUME NAME
local 1b0c55f6797e20040e0b51cb7922c370b2e7f0ae735f605daa3a4fe554e2af84
$ docker rm bbox
bbox
$ docker volume ls
DRIVER VOLUME NAME
local 1b0c55f6797e20040e0b51cb7922c370b2e7f0ae735f605daa3a4fe554e2af84
$ docker volume rm 1b0c55f6797e20040e0b51cb7922c370b2e7f0ae735f605daa3a4fe554e2af84
1b0c55f6797e20040e0b51cb7922c370b2e7f0ae735f605daa3a4fe554e2af84
$ docker volume ls
DRIVER VOLUME NAME
对于没有使用-v
参数的孤儿volume,可以使用docker volume rm
删除