# Docker数据共享与持久化
容器运行的 文件系统
处于沙盒环境中,与外界其实是隔离的。
Docker 容器中的文件系统系统的隔离性,虽然有很多优势,但也有很多弊端:
- 由于
沙盒文件系统
会跟随容器生命周期所创建和移除的,所以容器内的数据是无法持久化存储
。 - 由于
容器隔离
,我们很难从容器外部获得或操作容器内部文件中的数据。
Docker
容器 文件系统
是基于 UnionFS
。由于 UnionFS
支持 挂载不同类型
的 文件系统
到 统一的目录
结构中,所以我们只需要将宿主操作系统中,文件或目录挂载到容器中,便能够让容器内外共享这个文件。
由于通过这种方式可以互通容器内外的文件,那么文件数据持久化和操作容器内文件的问题就自然而然的解决了。
同时,UnionFS
带来的 读写性能
损失是可以忽略不计的,所以这种实现可以说是相当优秀的。
# 数据共享与持久化
在容器中管理数据,实现 数据共享
与 持久化
主要有两种⽅式:
- 数据卷(Data Volumes)
- 挂载主机⽬录 (Bind mounts)
# 数据卷
数据卷
是⼀个可供⼀个或多个容器使⽤的特殊⽬录,它绕过 UFS
,可以提供很多有⽤的特性:
- 数据卷 可以在容器之间共享和重⽤
- 对 数据卷 的修改会⽴⻢⽣效
- 对 数据卷 的更新,不会影响镜像
- 数据卷 默认会⼀直存在,即使容器被删除
注意:数据卷 的使⽤,类似于 Linux 下对⽬录或⽂件进⾏ mount,镜像中的被指定为挂载点的⽬录中的⽂件会隐藏掉,能显示看的是挂载的 数据卷。
数据卷的本质其实依然是宿主操作系统上的一个目录,只不过这个目录存放在 Docker 内部
,接受 Docker 的管理
。
# 创建⼀个数据卷
$ docker volume create volTest1
# 挂载数据卷
在⽤ docker run
命令的时候,可以使用 -v
或 --volume
选项来定义数据卷的挂载。来将 数据卷
挂载到容器⾥。
使用 -v
选项挂载数据卷时,如果数据卷不存在,Docker
会为我们自动创建和分配宿主操作系统的目录,而如果同名数据卷已经存在,则会直接引用。
# 格式
-v <container-path>
或 -v <volume-name>:<container-path>
如果没有指定 <volume-name>
,容器后台会自动创建挂载好。
# 删除数据卷
在删除数据卷之前,我们必须保证数据卷没有被任何容器所使用 ( 也就是之前引用过这个数据卷的容器都已经删除 ),否则 Docker
不会允许我们删除这个数据卷。
我们可以直接通过 docker volume rm
来删除指定的数据卷。
docker volume rm volTest1
数据卷
⽣命周期独⽴于容器,Docker
不会在容器被删除后 ⾃动删除
数据卷,并且也不存在 垃圾回收
这样的机制来处理没有任何容器 引⽤
的 数据卷
。
如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使⽤ docker rm -v
这个命令。
没有任何容器 引⽤
的数据卷可能会占据很多空间,删除那些没有被容器引用的数据卷:
docker volume prune
# 查看数据卷信息
使用 docker volume ls
查看所有的数据卷:
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local volTest1
我们可以通过 docker inspect
看到容器中数据卷挂载的详细信息。
[root@localhost ~]# docker inspect volTest1
[
{
"CreatedAt": "2020-07-30T09:21:43+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/volTest1/_data",
"Name": "volTest1",
"Options": {},
"Scope": "local"
}
]
# 挂载主机⽬录
要将容器中目录挂载到宿主操作系统中,我们可以在容器创建的时候通过传递 -v
或 --volume
选项来指定内外挂载的对应目录或文件。
定义绑定挂载时必须使用 绝对路径
。
# 格式
-v 宿主机目录:容器目录
# 实例
启动一个 Nginx 容器,将资源文件,日志文件挂载到宿主机的 /home/nginx
docker run -itd -p 80:80 --name jenkins-test \
-v /home/nginx/html:/usr/share/nginx/html \
-v /home/nginx/logs:/var/log/nginx \
--restart always \
nginx
查看容器数据挂载的详细信息:
docker inspect jenkins-test
"Mounts": [
{
"Type": "bind",
"Source": "/home/nginx/html",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/home/nginx/logs",
"Destination": "/var/log/nginx",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
在上面的挂载信息中,我们可以看到一个 RW
字段,这表示挂载目录或文件的读写性 ( Read and Write)。
实际操作中,Docker
还支持以只读的方式挂载,通过只读方式挂载的目录和文件,只能被容器中的程序读取,但不接受容器中程序修改它们的请求。
在挂载选项 -v
后再接上 :ro
就可以只读挂载了。
# 临时性挂载存储
Tmpfs Mount
是一种特殊的挂载方式,它主要利用 内存
来存储数据。由于内存不是持久性存储设备,所以其带给 Tmpfs Mount
的特征就是 临时性挂载
。
在⽤ docker run
命令的时候,可以使用 --tmpfs
选项来定义 临时性挂载
。
docker run -d --name webapp --tmpfs /webapp/cache webapp:latest
# 使用场景
- 不需要进行持久保存的敏感数据,可以借助
内存的非持久性
和程序隔离性
进行一定的安全保障。 - 对读写速度要求较高,并发要求高,但不需要持久保存的数据,可以借助内存的
高读写
速度减少请求的时间。
# 参考
← Docker网络 Docker 的技术实现 →