容器数据持久化

容器数据管理

容器写数据原理:

  • Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层
  • 基于写实复制(cow),只读层的内容需要修改时,把文件复制到读写层,在读写层进行修改,而只读层的数据没有修改,但此时还是在容器内部的数据持久化,容器删除修改后的数据也删除,但使用volume可以将数据存在宿主机

容器的数据管理:

Docker镜像是分层设计的,镜像层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层中

容器的数据分层目录:

  • LowerDir: image镜像层,容器基于哪个镜像运行的,只读层
  • UpperDir: 容器的上层(读写层),容器变化的数据存放在此处
  • MergedDir: 容器的文件系统,使用Union-FS(联合文件系统)将lowerdir和upperdir合并完成后给容器使用,最终呈现给用户的统一视图,也就是容器中的根文件系统
  • WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见

查看分层数据目录: docker inspect n1 |grep -A 5 Data

哪些数据需要持久化:

有状态协议就是就通信双方要记住双方,并且共享一些信息。而无状态协议的通信每次都是独立的,与上一次的通信没什么关系
"状态”可以理解为“记忆”,有状态对应有记忆,无状态对应无记忆

数据持久化方式:

如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录

两种方式

  • 数据卷(Data Volume),直接将宿主机目录挂载到容器的指定目录,推荐使用
  • 数据卷容器(Data Volume Containe),间接使用宿主机空间,数据卷容器是将物理机的目录挂载到一个专门的数据卷容器(做服务器),其他容器通过数据卷容器读写宿主机的数据,此方法不常用

数据卷:

数据卷使用场景

  • 数据库
  • 日志输出
  • 静态web页面
  • 应用配置文件
  • 多容器间目录或文件共享

数据卷特点

  • 数据卷是目录或文件,且可以在多个容器之间共同使用。实现同期之间共享和重用
  • 对数据卷更改数据在所有容器里面会立即更新
  • 数据卷的数据可以持久化保存,删除容器后仍然存在
  • 在容器里面写入数据不会影响到镜像
  • 依赖于宿主机目录,宿主机出问题,容器会受影响,当宿主机较多时,不方便统一管理
  • 匿名和命名数据卷在容器启动时初始化,如果宿主机目录有数据,容器内也能看到数据

数据卷使用方法:

三种方法

  • 指定文件映射: 运行时指定宿主机的具体路径和容器路径的挂载关系
  • 匿名卷: 只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,把容器内的目录存下来,存在哪不管,由docker决定宿主机存储位置
  • 命名卷: 指定数据卷的名称和容器路径的挂载关系

用法:

创建数据卷:
docker run -v [host-src:]container-dest[:选项]
选项:
	ro		从容器内对数据卷是只读,默认为可读可写 
	rw		容器对此数据卷可读写
删除数据卷:
docker rm -v 			只能删除匿名卷
docker volume rm `docker volume ls -q` 删除所有卷
docker volume命令:
docker volume cmd [选项] 卷
cmd命令:
	create		创卷卷
	inspect		显示详细信息
		-f string	指定显示内容
	ls			
		-q 		只显示卷名
		-f 内容		过滤显示
	prune		清理空间
		-f 		强制删除
	rm 			删除卷
		-f 		强制删除

使用数据卷方法

方式1:指定映射关系
-v <宿主机绝对路径目录/文件>:<容器目录/文件>[:ro]
方式2:指定容器内路径,宿主机路径自动生成:/var/lib/docker/volumes/<卷ID>/_data目录
-v <容器内路径>
方式3:数据卷名和容器路径,固定的存放在/var/lib/docker/volumes/<卷名>/_data
-v <卷名>:<容器目录路径>			自动生成卷
docker volume create 卷名		手动创建卷

docker run -d -P 80 --name ngx1 -v vol1:/data/html nginx

指定物理机和容器目录映射方式:

例:本地网页,给nginx容器使用
mkdir /data/web 
echo "nginx web v1" > /data/web/index.html
docker run -dp 81:80 -v /data/web:/opt/nginx/html --name n1 hj-ngx-ctos8:v3
docker run -dp 82:80 -v /data/web:/opt/nginx/html --name n2 hj-ngx-ctos8:v3
例:mysql容器,数据库持久化
mkdir /data/mysql
tee env.list <<EOF 
MYSQL_ROOT_PASSWORD=123456 
MYSQL_DATABASE=hj 
MYSQL_USER=hj 
MYSQL_PASSWORD=123456 
EOF

cat /root/mysql <<eof
[mysqld]
skip-name-resolve
bin-log
eof

docker pull mysql:5.7.30
docker run -dp 3306:3306 -v /data/mysql:/var/lib/mysql -v /root/mysql:/etc/mysql/conf.d/ --env-file=/opt/env.list --name sql mysql:5.7.30

匿名卷:

宿主机随机生成目录

docker run -dp 80:80 -v /usr/share/nginx/html --name n1 nginx
docker rm -fv n1 	删除容器时删除卷,-v只能用来删除匿名卷	

命名数据卷:

就是把匿名卷随机生成的卷id变成指定卷名

docker volume create hj_vol
docker volume ls

#当数据卷不存在时,直接指定会自动创建
docker run -dp 80:80 -v hj_vol:/opt/nginx/html --name n1 hj-ngx-ctos8:v3

容器卷:

由于匿名卷不能多个容器共同使用,但基于容器卷方式,可以将一个数据卷提供给多个容器使用
A容器做服务器,他使用一个数据卷
B和C容器做客户端,她们使用A容器的数据卷

注意

  • B、C容器除了创建时需要依赖A容器,创建成功后就不在依赖
  • 如A容器停止状态时,D容器还是能基于A的数据卷创建;但是A容器被删除了,D容器就无法基于A创建
  • 当B、C、D容器都创建且运行成功后,A容器被删除并不会影响其他的使用

docker run命令实现:

指定数据卷的容器

docker run --volumes-from 容器主机

为nginx做共享容器卷:

1)A容器
docker run -d --name ctos -v /data/web:/opt/nginx/html centos tail -f /etc/hosts
2)B和C容器
docker run -dp 80:80 --name n1 --volumes-from ctos hj-ngx-ctos8:v3
docker run -dp 81:80 --name n2 --volumes-from ctos hj-ngx-ctos8:v3
docker inspect n1|grep -A 8 Mounts	查看卷挂载

使用匿名卷时,做数据持久化:

匿名卷时不方便查询物理机的存储位置,此时可以再开一个容器,这个容器也是使用共享容器卷,但再指定一个本地数据卷,把容器卷的内容保存在自己的数据卷

1)A容器用匿名卷
docker run -dt --name al -v /data alpine tail -f /etc/hosts
2)B容器做数据持久备份
docker run -it --rm --name bak -v /opt/bak:/bak --volumes-from al centos tar czvf /bak/bak.tgz /data/
3)模拟A容器数据丢失
docker exec -it al sh
rm -rf /data
4)用B容器的备份恢复数据
docker run -it --rm --name bak -v /opt/bak:/bak --volumes-from al centos sh -c 'tar xzvf /bak/bak.tgz -C /'
posted @ 2022-02-24 11:34  suyanhj  阅读(136)  评论(0)    收藏  举报