0
点赞
收藏
分享

微信扫一扫

10、Docker利用数据卷实现容器数据持久化与数据卷容器

Docker利用数据卷实现容器数据持久化

docker容器的分层

容器的数据分层目录 
LowerDir: image 镜像层,即镜像本身,只读 
UpperDir: 容器的上层,可读写,容器变化的数据存放在此处,创建好容器,修改了数据,新生的的修改数据放在此处
MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成后给容器使用,最终呈现给用户的统一视图 
WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见

查看分层信息
[root@ubuntu2004 ~]#docker inspect nginx

哪些数据需要持久化

有状态的协议:通信双方要记住双方,并且共享一些信息
无状态的协议:通信每次都是独立的,与上一次的通讯没什么关系

容器数据持久保存方式

数据卷(Data Volume): 直接将宿主机目录挂载至容器的指定的目录,推荐使用此种方式,此方式较常用 
数据卷容器(Data Volume Container): 间接使用宿主机空间,数据卷容器是将宿主机的目录挂载至 一个专门的数据卷容器,然后让其他容器通过数据卷容器读写宿主机的数据 ,此方式不常用

数据卷分类

启动容器时,可以指定使用数据卷实现容器数据的持久化,数据卷有三种 

1、指定宿主机目录或文件: 指定宿主机的具体路径和容器路径的挂载关系,此方式不会创建数据卷 
2、匿名卷: 不指定数据名称,只指定容器内目录路径充当挂载点,docker自动指定宿主机的路径进行挂载,此方式会创建匿名数据卷,Dockerfile中VOLUME指定的卷即为此种 
3、命名卷: 指定数据卷的名称和容器路径的挂载关系,此方式会创建命名数据卷

数据卷使用方法

ro 从容器内对此数据卷是只读,不写此项默认为可读可写 
rw 从容器内对此数据卷可读可写,此为默认值
-v 指定方式

方式一:

#指定宿主机目录或文件格式:
-v   <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro]  #将宿主机目录挂载容器目录,两个目录都可自动创建

案例:
[root@ubuntu2004 nginx]#docker run -d -p 80:80 --name nginx01 -v /opt/test:/data/test/ nginx:v1.22.0-1
目录自动生成
[root@ubuntu2004 nginx]#ls /opt/test/
进入容器查看是否生成目录
[root@ubuntu2004 nginx]#docker exec -it nginx01 bash
root@ef408ca4a833:/# ls /data/test/
在宿主机建文件去容器查看是否有这个文件
[root@ubuntu2004 nginx]#cd /opt/test/
[root@ubuntu2004 test]#ls
[root@ubuntu2004 test]#touch a.txt
[root@ubuntu2004 test]#ls
a.txt
容器查看
root@ef408ca4a833:/# ls /data/test/
a.txt

如果容器内目录有数据,宿主机数据一旦挂载,容器内的数据将和宿主机数据一样
容器内的数据和宿主机数据保持一致
Dockerfile就可以省略 ADD index.html.tar.gz /apps/nginx/html/ 直接放在宿主机下就可以
例如:把Dockerfile中的ADD注释#ADD index.html.tar.gz /apps/nginx/html/
重新打镜像跑容器
[root@ubuntu2004 nginx]#bash build.sh v1.22.0-1
[root@ubuntu2004 nginx]#docker run -d -p 80:80 --name nginx01 -v /opt/test:/apps/nginx/html nginx:v1.22.0-1

在宿主机写页面
[root@ubuntu2004 nginx]#cd /opt/test/
[root@ubuntu2004 test]#echo website on host > index.html
[root@ubuntu2004 test]#pwd
/opt/test
[root@ubuntu2004 test]#ls
a.txt  index.html
访问
[root@ubuntu2004 test]#curl 10.0.0.101
website on host
在宿主机上更新,容器上的也更新了

方式二:匿名卷

#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径 
-v <容器内路径>
示例:
[root@ubuntu2004]#docker run -d -p 80:80 --name nginx01 -v /nginx/www nginx:v1.22.0-1
查看宿主机生成的匿名卷
[root@ubuntu2004 test]#ls /var/lib/docker/volumes/ -lt
total 36
drwx-----x 3 root root   4096 Oct 20 10:45 7a52ae7e7fc8baa0fab14e5e7db823ce2ead5723748de3d89068b8685c958daa
-rw------- 1 root root  32768 Oct 20 10:45 metadata.db
brw------- 1 root root 253, 0 Oct 20 08:48 backingFsBlockDev
drwx-----x 3 root root   4096 Oct 18 15:23 2d5607da3961bb796525b1f87d1990b75ba7c301d4ddddab7492e158f1876679
drwx-----x 3 root root   4096 Oct 18 15:16 8b58cbcb56357951d6d084fd235ab878f69b58e7f05ab0b10f73478c144f79e8

在宿主机这个目录下建个文件
[root@ubuntu2004 volumes]#touch 7a52ae7e7fc8baa0fab14e5e7db823ce2ead5723748de3d89068b8685c958daa/_data/123.txt
[root@ubuntu2004 volumes]#ls 7a52ae7e7fc8baa0fab14e5e7db823ce2ead5723748de3d89068b8685c958daa/_data/
123.txt
去容器查看
[root@ubuntu2004 volumes]#docker exec nginx01 ls -l /nginx/www
total 0
-rw-r--r-- 1 root root 0 Oct 20 10:49 123.txt

在容器建文件
root@77dfdfc3d189:/# echo hehe > /nginx/www/abc.txt
root@77dfdfc3d189:/# ls /nginx/www/
123.txt  abc.txt
去宿主机查看
[root@ubuntu2004 ~]#cat /var/lib/docker/volumes/7a52ae7e7fc8baa0fab14e5e7db823ce2ead5723748de3d89068b8685c958daa/_data/abc.txt 
hehe

docker rm 的-v选项可以删除容器时,同时删除相关联的匿名卷
[root@ubuntu2004 ~]#docker rm -f -v 77dfdfc3d189

方式三:命名卷

#命名卷将固定的存放在/var/lib/docker/volume/<卷名>/_data
-v <卷名>:<容器目录路径>

#可以通过以下命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷
[root@ubuntu2004 ~]#docker volume create volume1(卷名)
volume1
[root@ubuntu2004 ~]#docker inspect volume1 
[
    {
        "CreatedAt": "2022-10-20T11:04:22+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/volume1/_data",  (文件路径)
        "Name": "volume1",
        "Options": {},
        "Scope": "local"
    }
]
或[root@ubuntu2004 ~]#docker volume ls
DRIVER    VOLUME NAME
local     2d5607da3961bb796525b1f87d1990b75ba7c301d4ddddab7492e158f1876679
local     8b58cbcb56357951d6d084fd235ab878f69b58e7f05ab0b10f73478c144f79e8
local     volume1

创建容器关联volume1
[root@ubuntu2004 ~]#docker run -d -p 80:80 --name nginx01 -v volume1:/nginx/www nginx:v1.22.0-1
在容器下建文件
[root@ubuntu2004 ~]#docker exec nginx01 touch /nginx/www/1.txt
去/var/lib/docker/volumes/volume1/_data查看
[root@ubuntu2004 ~]#ls /var/lib/docker/volumes/volume1/_data/
1.txt
删除容器volume下的内容不会消失

#示例:docker volume create vol1 也可以是事先不创建
docker run -d -p 80:80 --name nginx01 -v vol1:/usr/share/nginx/html nginx 自动创建vol1

删除命名卷
docker volume prune (不再使用的)
docker volume rm (删除一个)

两个容器共享一个文件夹
[root@ubuntu2004 ~]#docker run -d -p 80:80 --name nginx01 -v volume1:/apps/nginx/html/ nginx:v1.22.0-1 
ffd36b25c8079a3554697cc41612bfd24a323295fc71bfd7f188284c79d53b86
[root@ubuntu2004 ~]#docker run -d -p 81:80 --name nginx02 -v volume1:/apps/nginx/html/ nginx:v1.22.0-1 
0e64b3c46f02ab38657928329c80737e37e41872e04b8d694e8d99b538d4e8a0
查看volume1文件下数据
[root@ubuntu2004 ~]#ls /var/lib/docker/volumes/volume1/_data/
50x.html  index.html
更改index.html页面
[root@ubuntu2004 ~]#curl 10.0.0.101
share website
[root@ubuntu2004 ~]#curl 10.0.0.101:81
share website
[root@ubuntu2004 ~]#
可看出两个容器共享一个文件夹

支持只读ro
[root@ubuntu2004 ~]#docker run -d -p 82:80 --name nginx03 -v volume1:/apps/nginx/html/:ro nginx:v1.22.0-1
宿主机更改html页面
[root@ubuntu2004 ~]#curl 10.0.0.101
share websit v2
[root@ubuntu2004 ~]#curl 10.0.0.101:81
share websit v2
[root@ubuntu2004 ~]#curl 10.0.0.101:82
share websit v2

进入nginx03并更改index.html改不了数据,因为设置了只读
进入nginx02并更改index.html
[root@ubuntu2004 ~]#curl 10.0.0.101
share websit v3
[root@ubuntu2004 ~]#curl 10.0.0.101:81
share websit v3
[root@ubuntu2004 ~]#curl 10.0.0.101:82
share websit v3
大家是共享的,访问加过都变

实战案例:实现wordpress持久化

[root@ubuntu2004 ~]#docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=123456 --name mysql -d -v /data/mysql:/var/lib/mysql --restart=always mysql:8.0.29-oracle


[root@ubuntu2004 ~]#docker run -d -p 80:80 --name wordpress -v /data/wordpess:/var/www/html --restart=always wordpress:php7.4-apache


[root@ubuntu2004 ~]#docker ps 
CONTAINER ID   IMAGE                     COMMAND                  CREATED              STATUS              PORTS                                                  NAMES
b531502419c6   wordpress:php7.4-apache   "docker-entrypoint.s…"   29 seconds ago       Up 28 seconds       0.0.0.0:80->80/tcp, :::80->80/tcp                      wordpress
4da9913ca386   mysql:8.0.29-oracle       "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
访问宿主机IP10.0.0.101
数据库地址:10.0.0.101

数据卷容器

先创建一个容器,带数据卷功能,其他容器调用前一个容器的数据卷

第一个容器有挂载关系,剩下的容器和第一个挂载相同,直接挂载第一个容器即可,即使删除第一个容器也不影响下的的容器

例如:
docker run -d --name nginx01 -p 80:80  -v volume1:/apps/nginx/html/ -v /data1:/data1 -v /data2:/data2 nginx:v1.22.0-1

docker run -d --name nginx02 -p 81:80  --volumes-from nginx01 nginx:v1.22.0-1
docker run -d --name nginx03 -p 82:80  --volumes-from nginx01 nginx:v1.22.0-1

如果容器用的是匿名卷挂载,并且不知道其所在宿主机的volumeID,如何将容器内的数据备份下来

创建需要备份的匿名卷容器
docker run -it -v /datavolume1 --name volume-server centos bash

进入容器在/datavolume1目录下创建数据
touch /datavolume1/centos.txt

退出容器并基于前面的匿名数据卷容器创建执行备份操作的容器
docker run -it --rm --volumes-from volume-server -v ~/backup:/backup --name backup-server ubuntu

进入该容器查看/datavolume1目录下的文件
root@9ad8be4b5810:/# ls /datavolume1/ 
centos.txt

把/datavolume1/目录下的数据打包到容器内的/backup目录下
root@9ad8be4b5810:/# cd /datavolume1/ 
root@9ad8be4b5810:/datavolume1# tar cvf /backup/data.tar . 
./ 
./centos.txt

退出容器查看当前家目录下的/backup目录
ls ~/backup/ 
data.tar

数据卷有几种存储方式

1、指定宿主机目录和指定容器目录
2、匿名卷:只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径 
3、命名卷: <卷名>:<容器目录路径>命名卷将固定的存放在/var/lib/docker/volume/<卷名>/_data

举报

相关推荐

0 条评论