48-Docker-多容器数据共享及持久化

2023-01-11 10:17:26 来源:51CTO博客

Docker镜像数据读写原理

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW copyon write)"机制COW机制节约空间,但会导致性低下,虽然关闭重启容器,数据不受影响,但会随着容器的删除,其对应的可写层也会随之而删除,即数据也会丢失.如果容器需要持久保存数据,并不影响性能可以用数据卷技术实现

Docker容器的分层


(资料图片仅供参考)

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

容器的数据分层目录

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

案例:

"GraphDriver": {            "Data": {                "LowerDir": "/data/docker/overlay2/086a9610ca8e8299ccfa6656cc8939f10d981c670eb3d8e0dace3578566e1950-init/diff:/data/docker/overlay2/3719ac9519537c60c9232d10a4f8cf8886795dd10dc77e1419366cf6620a6f4a/diff:/data/docker/overlay2/af7dbf5445243ce62ea3332d6e8de09ac9343507eb09c6bf33af1536d0ea4bb6/diff:/data/docker/overlay2/6c24180effae6e89f5340c4cb97d4d16cf16dc078ea07fd0c83d974a93d29390/diff:/data/docker/overlay2/37d92a852bed1006ae43fbb7370d279f5eac095ded055f1c3da31e114357ad87/diff:/data/docker/overlay2/6aaf443aeea3dfaac29f6d4a9ccad2b90a44cb1f69590ba4028168be32c65f27/diff:/data/docker/overlay2/c43183788449098ba9809d7a8a58666db201daef8eb41ef81e6ce9cbb6818df7/diff:/data/docker/overlay2/31316f8b67f97e6c4a9543dfc4328c0e3c29d52f7dfcdd1af66d66d0c658dcc7/diff:/data/docker/overlay2/4f1e571f109868c90e38a6f0538c5abf9daff5c47ffedb19894d56ce1edd9b37/diff",                "MergedDir": "/data/docker/overlay2/086a9610ca8e8299ccfa6656cc8939f10d981c670eb3d8e0dace3578566e1950/merged",                "UpperDir": "/data/docker/overlay2/086a9610ca8e8299ccfa6656cc8939f10d981c670eb3d8e0dace3578566e1950/diff",                "WorkDir": "/data/docker/overlay2/086a9610ca8e8299ccfa6656cc8939f10d981c670eb3d8e0dace3578566e1950/work"            },            "Name": "overlay2"        },

容器数据持久保存的两种方式

如果要将写入到容器的数据永久保存,则需要将容器中的数据保存到宿主机的指定目录Docker的数据类型分为两种:

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

1. 数据卷的使用

数据卷使用场景

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

数据卷的特点

数据卷是目录或者文件,并且可以在多个容器之间共同使用,实现容器之间共享和重用对数据卷更改数据在所有容器里面会立即更新。数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。在容器里面的写入数据不会影响到镜像本身,即数据卷的变化不会影响镜像的更新依赖于宿主机目录,宿主机出问题,上面容器会受影响,当宿主机较多时,不方便统一管理匿名和命名数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,会拷贝到新初始化的数据卷中

数据卷分类

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

数据卷使用语法

-v, --volume=[host-src:]container-dest[:]ro 从容器内对此数据卷是只读,不写此项默认为可读可写rw 从容器内对此数据卷可读可写,此为默认值方式1:#指定宿主机目录或文件格式:-v <宿主机绝对路径的目录或文件>:<容器目录或文件>[:ro] #将宿主机目录挂载容器目录,两个目录都可自动创建案例:[root@ubuntu2204 ~]#mkdir -pv /opt/nginx/html/mkdir: 已创建目录 "/opt/nginx"mkdir: 已创建目录 "/opt/nginx/html/"[root@ubuntu2204 ~]#echo "Hello Moore,Nice to meet you" > /opt/nginx/html/index.html[root@ubuntu2204 ~]#docker run -d -p 8080:80 -v /opt/nginx/html/:/data/nginx/html/  nginx-alpine:1.16.1bb8b25caf71b1b641a5d25c45f074a7c4c5e611374214e97bcf6c8eeb2f218d3[root@ubuntu2204 ~]#curl 127.0.0.1:8080Hello Moore,Nice to meet you------------------------------------------------------------------------------------------------方式2#匿名卷,只指定容器内路径,没有指定宿主机路径信息,宿主机自动生成/var/lib/docker/volumes/<卷ID>/_data目录,并挂载至容器指定路径-v <容器内路径>#案例:[root@ubuntu2204 1.16.1-alpine]#cat Dockerfile FROM alpine-base:v1.2LABEL auther="mooreyxia" \      version="1.0" ADD nginx-1.16.1.tar.gz /usr/local/srcRUN cd /usr/local/src/nginx-1.16.1 \    && ./configure --prefix=/apps/nginx \    && make && make install \    && ln -s /apps/nginx/sbin/nginx /usr/bin/ RUN addgroup -g 2019 -S nginx \    && adduser -s /sbin/nologin -S -D -u 2019 -G nginx nginxCOPY nginx.conf /apps/nginx/conf/nginx.confADD index.html /data/nginx/html/index.htmlRUN chown -R nginx.nginx /data/nginx/ /apps/nginx/EXPOSE 80 443CMD ["nginx"]VOLUME /data/nginx/html/ --> Dockerfile中直接设置也可 #或者在run命令中直接指定,生成的数据卷名称是随机的[root@ubuntu2204 1.16.1-alpine]#docker run -d -p 83:80 -v /data/nginx/html/ --name anon-server  nginx-alpine:1.16.1d10e8dcb46a335b9cc3d8ae4322c51f501a45da96d660e0d84bb0c79352027f1[root@ubuntu2204 1.16.1-alpine]#docker volume lsDRIVER    VOLUME NAMElocal     169341e0045107bbdea856220db8221082c950408918d7c58f03fffc09e73997------------------------------------------------------------------------------------------------方式3#命名卷将固定的存放在/var/lib/docker/volumes/<卷名>/_data-v <卷名>:<容器目录路径>#可以通过命令事先创建,如可没有事先创建卷名,docker run时也会自动创建卷docker volume create <卷名>案例:[root@ubuntu2204 1.16.1-alpine]#docker run -d -p 84:80 -v website:/data/nginx/html/  nginx-alpine:1.16.1f895a3ce97ac7fd6cd1935dc92311f6f921deb161f8bb396ea7a92f7ef7db6ab[root@ubuntu2204 1.16.1-alpine]#docker volume lsDRIVER    VOLUME NAMElocal     website

管理数据卷命令

#数据卷的删除或者是不用的数据卷都可以删除,用rm -f 的方式容易有残留文件[root@ubuntu2204 1.16.1-alpine]#docker volume --helpUsage:  docker volume COMMANDManage volumesCommands:  create      Create a volume  inspect     Display detailed information on one or more volumes  ls          List volumes  prune       Remove all unused local volumes  rm          Remove one or more volumesRun "docker volume COMMAND --help" for more information on a command.案例:删除没有被使用的数据卷[root@ubuntu2204 1.16.1-alpine]#docker psCONTAINER ID   IMAGE                   COMMAND   CREATED          STATUS          PORTS                                        NAMESf895a3ce97ac   nginx-alpine:1.16.1     "nginx"   6 minutes ago    Up 6 minutes    443/tcp, 0.0.0.0:84->80/tcp, :::84->80/tcp   intelligent_matsumotod10e8dcb46a3   nginx-alpine:1.16.1     "nginx"   16 minutes ago   Up 16 minutes   443/tcp, 0.0.0.0:83->80/tcp, :::83->80/tcp   anon-server2374dfc04840   nginx-alpine:1.16.1-1   "nginx"   2 hours ago      Up 2 hours      443/tcp, 0.0.0.0:90->80/tcp, :::90->80/tcp   data-server1f345b2624792   nginx-alpine:1.16.1     "nginx"   2 hours ago      Up 2 hours      443/tcp, 0.0.0.0:81->80/tcp, :::81->80/tcp   server15c7d31a7764a   nginx-alpine:1.16.1     "nginx"   2 hours ago      Up 2 hours      443/tcp, 0.0.0.0:82->80/tcp, :::82->80/tcp   server2176f11e9ee8c   nginx-alpine:1.16.1     "nginx"   3 hours ago      Up 3 hours      0.0.0.0:80->80/tcp, :::80->80/tcp, 443/tcp   data-server[root@ubuntu2204 1.16.1-alpine]#docker rm -f intelligent_matsumotointelligent_matsumoto[root@ubuntu2204 1.16.1-alpine]#docker rm -f anon-serveranon-server[root@ubuntu2204 1.16.1-alpine]#docker volume lsDRIVER    VOLUME NAMElocal     169341e0045107bbdea856220db8221082c950408918d7c58f03fffc09e73997local     website[root@ubuntu2204 1.16.1-alpine]#docker volume rm 169341e00451 website

案例:引用同一个数据卷目录,开启多个容器,实现多个容器共享数据

[root@ubuntu2204 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p8001:80 nginx-alpine:1.16.156a5460f584bd2de56040c4a1dff86ad8a9723cfd6bf21ed8a538b9629b0874c[root@ubuntu2204 ~]#docker run -d -v /data/testdir:/data/nginx/html/ -p8002:80 nginx-alpine:1.16.1e7b5bff6ce56fa51ed6411175c9c9f1fb9bf8e7b1b9471080380b01692f89e58[root@ubuntu2204 ~]#docker psCONTAINER ID IMAGE COMMAND CREATEDSTATUS PORTS NAMESe7b5bff6ce56 nginx-alpine:1.16.1 "nginx" 6 seconds agoUp 5 seconds 443/tcp, 0.0.0.0:8002->80/tcp hungry_robinson56a5460f584b nginx-alpine:1.16.1 "nginx" 33 seconds agoUp 31 seconds 443/tcp, 0.0.0.0:8001->80/tcp stupefied_dubinsky[root@ubuntu2204 ~]#curl 127.0.0.1:8001Test page on host[root@ubuntu2204 ~]#curl 127.0.0.1:8002Test page on host

数据卷容器

数据卷容器最大的功能是可以让数据在多个docker容器之间共享

实现方式:

先要创建一个后台运行的容器作为 Server,用于提供数据卷,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为client端 ,但此方法并不常使用缺点: 因为依赖一个 Server 的容器,所以此 Server 容器出了问题,其它 Client容器都会受影响

案例:

#--volumes-from <数据卷容器> Mount volumes from the specified container(s)#创建一个后台运行的容器作为 Server,用于提供数据卷[root@ubuntu2204 ~]#docker run -d -p 80:80 -v /opt/nginx/html/:/data/nginx/html/ -v /opt/dir1:/dir1 --name data-server nginx-alpine:1.16.1176f11e9ee8c1e8873bc05ed5820f2a80a3d330e250c22030d3bb2ff371233be[root@ubuntu2204 ~]#docker ps CONTAINER ID   IMAGE                 COMMAND   CREATED          STATUS          PORTS                                        NAMES176f11e9ee8c   nginx-alpine:1.16.1   "nginx"   13 seconds ago   Up 12 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp, 443/tcp   data-server[root@ubuntu2204 ~]#docker volume lsDRIVER    VOLUME NAME[root@ubuntu2204 ~]#curl 127.0.0.1Hello Moore,Nice to meet you[root@ubuntu2204 ~]#touch /opt/dir1/abc.txt[root@ubuntu2204 ~]#docker exec data-server ls /dir1abc.txt#其他使用此卷的容器作为client端[root@ubuntu2204 ~]#docker run -d -p 82:80 --name server2 --volumes-from data-server  nginx-alpine:1.16.15c7d31a7764a0a3b561fd86107a1676f9d60db54fdb72ebfac67bed3c769ef9f[root@ubuntu2204 ~]#docker run -d -p 81:80 --name server1 --volumes-from data-server  nginx-alpine:1.16.1f345b26247924e27d89e2bdce21a78ae4faf162f01a49be8116460d8ab66f514[root@ubuntu2204 ~]#docker psCONTAINER ID   IMAGE                 COMMAND   CREATED          STATUS          PORTS                                        NAMESf345b2624792   nginx-alpine:1.16.1   "nginx"   4 seconds ago    Up 3 seconds    443/tcp, 0.0.0.0:81->80/tcp, :::81->80/tcp   server15c7d31a7764a   nginx-alpine:1.16.1   "nginx"   30 seconds ago   Up 29 seconds   443/tcp, 0.0.0.0:82->80/tcp, :::82->80/tcp   server2176f11e9ee8c   nginx-alpine:1.16.1   "nginx"   8 minutes ago    Up 8 minutes    0.0.0.0:80->80/tcp, :::80->80/tcp, 443/tcp   data-server[root@ubuntu2204 ~]#curl 127.0.0.1:80Hello Moore,Nice to meet you[root@ubuntu2204 ~]#curl 127.0.0.1:81Hello Moore,Nice to meet you[root@ubuntu2204 ~]#curl 127.0.0.1:82Hello Moore,Nice to meet you[root@ubuntu2204 ~]#docker exec server2 ls /dir1abc.txt[root@ubuntu2204 ~]#docker exec server1 ls /dir1abc.txt

注意:

删除数据卷容器后,旧的client 容器仍能访问,但无法再创建新的client容器删除数据卷容器后,旧的client 容器仍能访问,但无法再创建基于数据卷容器的新的client容器,但可以创建基于已创建的Client容器的Client容器

利用数据卷容器备份指定容器的数据卷实现

为了方便的备份匿名数据卷,可以利用数据卷容器实现数据卷的备份

#使用语法#在执行备份命令容器上执行备份方式docker run -it --rm --volumes-from [container name] -v $(pwd):/backup ubunturoot@ca5bb2c1f877:/#tar cvf /backup/backup.tar [container data volume]#说明[container name] #表示需要备份的容器[container data volume] #表示容器内的需要备份的数据卷对应的目录#还原方式docker run -it --rm --volumes-from [container name] -V $(pwd):/backup ubunturoot@ca5bb2c1f877:/#tar xvf /backup/backup.tar -C [container data volume]案例:[root@ubuntu2204 ~]#vim /data/docker/volumes/169341e0045107bbdea856220db8221082c950408918d7c58f03fffc09e73997/_data/index.html [root@ubuntu2204 ~]#curl 127.0.0.1:90Test Page based nginx-alpine v2.0[root@ubuntu2204 ~]#docker run -it --rm --volumes-from data-server1 -v $(pwd):/backup nginx-alpine:1.16.1-1 tar cvf /backup/backup.tar /data/nginx/htmltar: removing leading "/" from member namesdata/nginx/html/data/nginx/html/index.html[root@ubuntu2204 ~]#lsbackup.tar  install_docker.sh  nginx-1.16.1.tar.gz  nginx_install.sh  repositories  web02_status.txt[root@ubuntu2204 ~]#tar tvf backup.tar drwxr-xr-x nginx/nginx       0 2023-01-10 16:49 data/nginx/html/-rw-r--r-- nginx/nginx      34 2023-01-10 16:49 data/nginx/html/index.html[root@ubuntu2204 ~]#docker volume lsDRIVER    VOLUME NAMElocal     169341e0045107bbdea856220db8221082c950408918d7c58f03fffc09e73997#故意破环容器内数据[root@ubuntu2204 ~]#rm -f /data/docker/volumes/169341e0045107bbdea856220db8221082c950408918d7c58f03fffc09e73997/_data/index.html [root@ubuntu2204 ~]#curl 127.0.0.1:90403 Forbidden

403 Forbidden


nginx/1.16.1
#还原数据[root@ubuntu2204 ~]#docker run -it --rm --volumes-from data-server1 -v $(pwd):/backup nginx-alpine:1.16.1-1 sh/ # ls /backup/backup.tar install_docker.sh nginx-1.16.1.tar.gz nginx_install.sh repositories web02_status.txt/ # tar xf /backup/backup.tar / # lsapps backup bin data dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var/ # ls /data/nginx/html/index.html/ # exit[root@ubuntu2204 ~]#curl 127.0.0.1:90Test Page based nginx-alpine v2.0

数据卷容器总结 - 实现多个客户端容器共享相同的持久化宿主机的存储方案

将提供卷的容器Server 删除,已经运行的容器Client依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器Server创建后即可正常创建卷容器Client,此方式可以用于线上共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用。由此可知, 数据卷容器的功能只是将数据挂载信息传递给了其它使用数据卷容器的容器,而数据卷容器本身并不提供数据存储功能数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于NFS共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性当创建Client容器时,会复制Server容器的数据卷信息,后续Server容器状态和存在与否,都不会影响Client容器使用的数据卷当Server容器删除后,不能再基于Server容器创建新的Client容器,但可以基于已存在的Client容器来创建新的Client容器

我是moore,大家一起加油!

标签: 提供数据

上一篇:跨地域OSSIM传感器部署实战
下一篇:环球新动态:运用c语言完成简单的猜数字游戏(随机数为1到100)