
Docker鏡像數(shù)據(jù)讀寫原理
Docker鏡像由多個(gè)只讀層疊加而成,啟動(dòng)容器時(shí),Docker會(huì)加載只讀鏡像層并在鏡像棧頂部添加一個(gè)讀寫層如果運(yùn)行中的容器修改了現(xiàn)有的一個(gè)已經(jīng)存在的文件,那該文件將會(huì)從讀寫層下面的只讀層復(fù)制到讀寫層,該文件的只讀版本仍然存在,只是已經(jīng)被讀寫層中該文件的副本所隱藏,此即“寫時(shí)復(fù)制(COW copyon write)"機(jī)制COW機(jī)制節(jié)約空間,但會(huì)導(dǎo)致性低下,雖然關(guān)閉重啟容器,數(shù)據(jù)不受影響,但會(huì)隨著容器的刪除,其對(duì)應(yīng)的可寫層也會(huì)隨之而刪除,即數(shù)據(jù)也會(huì)丟失.如果容器需要持久保存數(shù)據(jù),并不影響性能可以用數(shù)據(jù)卷技術(shù)實(shí)現(xiàn)Docker容器的分層
(資料圖片僅供參考)
Docker鏡像是分層設(shè)計(jì)的,鏡像層是只讀的,通過(guò)鏡像啟動(dòng)的容器添加了一層可讀寫的文件系統(tǒng),用戶寫入的數(shù)據(jù)都保存在這一層中。
容器的數(shù)據(jù)分層目錄
LowerDir: image 鏡像層,即鏡像本身,只讀UpperDir: 容器的上層,可讀寫 ,容器變化的數(shù)據(jù)存放在此處MergedDir: 容器的文件系統(tǒng),使用Union FS(聯(lián)合文件系統(tǒng))將lowerdir 和 upperdir 合并完成后給容器使用,最終呈現(xiàn)給用戶的統(tǒng)一視圖WorkDir: 容器在宿主機(jī)的工作目錄,掛載后內(nèi)容會(huì)被清空,且在使用過(guò)程中其內(nèi)容用戶不可見(jiàn)案例:
"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" },
容器數(shù)據(jù)持久保存的兩種方式
如果要將寫入到容器的數(shù)據(jù)永久保存,則需要將容器中的數(shù)據(jù)保存到宿主機(jī)的指定目錄Docker的數(shù)據(jù)類型分為兩種:
數(shù)據(jù)卷(Data Volume): 直接將宿主機(jī)目錄掛載至容器的指定的目錄 ,推薦使用此種方式數(shù)據(jù)卷容器(Data Volume Container): 間接使用宿主機(jī)空間,數(shù)據(jù)卷容器是將宿主機(jī)的目錄掛載至一個(gè)專門的數(shù)據(jù)卷容器,然后讓其他容器通過(guò)數(shù)據(jù)卷容器讀寫宿主機(jī)的數(shù)據(jù) ,此方式不常用1. 數(shù)據(jù)卷的使用
數(shù)據(jù)卷使用場(chǎng)景
數(shù)據(jù)庫(kù)日志輸出靜態(tài)web頁(yè)面應(yīng)用配置文件多容器間目錄或文件共享數(shù)據(jù)卷的特點(diǎn)
數(shù)據(jù)卷是目錄或者文件,并且可以在多個(gè)容器之間共同使用,實(shí)現(xiàn)容器之間共享和重用對(duì)數(shù)據(jù)卷更改數(shù)據(jù)在所有容器里面會(huì)立即更新。數(shù)據(jù)卷的數(shù)據(jù)可以持久保存,即使刪除使用使用該容器卷的容器也不影響。在容器里面的寫入數(shù)據(jù)不會(huì)影響到鏡像本身,即數(shù)據(jù)卷的變化不會(huì)影響鏡像的更新依賴于宿主機(jī)目錄,宿主機(jī)出問(wèn)題,上面容器會(huì)受影響,當(dāng)宿主機(jī)較多時(shí),不方便統(tǒng)一管理匿名和命名數(shù)據(jù)卷在容器啟動(dòng)時(shí)初始化,如果容器使用的鏡像在掛載點(diǎn)包含了數(shù)據(jù),會(huì)拷貝到新初始化的數(shù)據(jù)卷中數(shù)據(jù)卷分類
指定宿主機(jī)目錄或文件: 指定宿主機(jī)的具體路徑和容器路徑的掛載關(guān)系,此方式不會(huì)創(chuàng)建數(shù)據(jù)卷匿名卷: 不指定數(shù)據(jù)名稱,只指定容器內(nèi)目錄路徑充當(dāng)掛載點(diǎn),docker自動(dòng)指定宿主機(jī)的路徑進(jìn)行掛載,此方式會(huì)創(chuàng)建匿名數(shù)據(jù)卷,Dockerfile中VOLUME指定的卷即為此種命名卷: 指定數(shù)據(jù)卷的名稱和容器路徑的掛載關(guān)系,此方式會(huì)創(chuàng)建命名數(shù)據(jù)卷數(shù)據(jù)卷使用語(yǔ)法
-v, --volume=[host-src:]container-dest[:] ro 從容器內(nèi)對(duì)此數(shù)據(jù)卷是只讀,不寫此項(xiàng)默認(rèn)為可讀可寫rw 從容器內(nèi)對(duì)此數(shù)據(jù)卷可讀可寫,此為默認(rèn)值方式1:#指定宿主機(jī)目錄或文件格式:-v <宿主機(jī)絕對(duì)路徑的目錄或文件>:<容器目錄或文件>[:ro] #將宿主機(jī)目錄掛載容器目錄,兩個(gè)目錄都可自動(dòng)創(chuàng)建案例:[root@ubuntu2204 ~]#mkdir -pv /opt/nginx/html/mkdir: 已創(chuàng)建目錄 "/opt/nginx"mkdir: 已創(chuàng)建目錄 "/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#匿名卷,只指定容器內(nèi)路徑,沒(méi)有指定宿主機(jī)路徑信息,宿主機(jī)自動(dòng)生成/var/lib/docker/volumes/<卷ID>/_data目錄,并掛載至容器指定路徑-v <容器內(nèi)路徑>#案例:[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中直接設(shè)置也可 #或者在run命令中直接指定,生成的數(shù)據(jù)卷名稱是隨機(jī)的[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 <卷名>:<容器目錄路徑>#可以通過(guò)命令事先創(chuàng)建,如可沒(méi)有事先創(chuàng)建卷名,docker run時(shí)也會(huì)自動(dòng)創(chuàng)建卷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
管理數(shù)據(jù)卷命令
#數(shù)據(jù)卷的刪除或者是不用的數(shù)據(jù)卷都可以刪除,用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.案例:刪除沒(méi)有被使用的數(shù)據(jù)卷[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
案例:引用同一個(gè)數(shù)據(jù)卷目錄,開啟多個(gè)容器,實(shí)現(xiàn)多個(gè)容器共享數(shù)據(jù)
[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
數(shù)據(jù)卷容器
數(shù)據(jù)卷容器最大的功能是可以讓數(shù)據(jù)在多個(gè)docker容器之間共享
實(shí)現(xiàn)方式:
先要?jiǎng)?chuàng)建一個(gè)后臺(tái)運(yùn)行的容器作為 Server,用于提供數(shù)據(jù)卷,這個(gè)卷可以為其他容器提供數(shù)據(jù)存儲(chǔ)服務(wù),其他使用此卷的容器作為client端 ,但此方法并不常使用缺點(diǎn): 因?yàn)橐蕾囈粋€(gè) Server 的容器,所以此 Server 容器出了問(wèn)題,其它 Client容器都會(huì)受影響案例:
#--volumes-from <數(shù)據(jù)卷容器> Mount volumes from the specified container(s)#創(chuàng)建一個(gè)后臺(tái)運(yùn)行的容器作為 Server,用于提供數(shù)據(jù)卷[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
注意:
刪除數(shù)據(jù)卷容器后,舊的client 容器仍能訪問(wèn),但無(wú)法再創(chuàng)建新的client容器刪除數(shù)據(jù)卷容器后,舊的client 容器仍能訪問(wèn),但無(wú)法再創(chuàng)建基于數(shù)據(jù)卷容器的新的client容器,但可以創(chuàng)建基于已創(chuàng)建的Client容器的Client容器利用數(shù)據(jù)卷容器備份指定容器的數(shù)據(jù)卷實(shí)現(xiàn)
為了方便的備份匿名數(shù)據(jù)卷,可以利用數(shù)據(jù)卷容器實(shí)現(xiàn)數(shù)據(jù)卷的備份
#使用語(yǔ)法#在執(zhí)行備份命令容器上執(zhí)行備份方式docker run -it --rm --volumes-from [container name] -v $(pwd):/backup ubunturoot@ca5bb2c1f877:/#tar cvf /backup/backup.tar [container data volume]#說(shuō)明[container name] #表示需要備份的容器[container data volume] #表示容器內(nèi)的需要備份的數(shù)據(jù)卷對(duì)應(yīng)的目錄#還原方式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#故意破環(huán)容器內(nèi)數(shù)據(jù)[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 #還原數(shù)據(jù)[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
數(shù)據(jù)卷容器總結(jié) - 實(shí)現(xiàn)多個(gè)客戶端容器共享相同的持久化宿主機(jī)的存儲(chǔ)方案
將提供卷的容器Server 刪除,已經(jīng)運(yùn)行的容器Client依然可以使用掛載的卷,因?yàn)槿萜魇峭ㄟ^(guò)掛載訪問(wèn)數(shù)據(jù)的,但是無(wú)法創(chuàng)建新的卷容器客戶端,但是再把卷容器Server創(chuàng)建后即可正常創(chuàng)建卷容器Client,此方式可以用于線上共享數(shù)據(jù)目錄等環(huán)境,因?yàn)榧词箶?shù)據(jù)卷容器被刪除了,其他已經(jīng)運(yùn)行的容器依然可以掛載使用。由此可知, 數(shù)據(jù)卷容器的功能只是將數(shù)據(jù)掛載信息傳遞給了其它使用數(shù)據(jù)卷容器的容器,而數(shù)據(jù)卷容器本身并不提供數(shù)據(jù)存儲(chǔ)功能數(shù)據(jù)卷容器可以作為共享的方式為其他容器提供文件共享,類似于NFS共享,可以在生產(chǎn)中啟動(dòng)一個(gè)實(shí)例掛載本地的目錄,然后其他的容器分別掛載此容器的目錄,即可保證各容器之間的數(shù)據(jù)一致性當(dāng)創(chuàng)建Client容器時(shí),會(huì)復(fù)制Server容器的數(shù)據(jù)卷信息,后續(xù)Server容器狀態(tài)和存在與否,都不會(huì)影響Client容器使用的數(shù)據(jù)卷當(dāng)Server容器刪除后,不能再基于Server容器創(chuàng)建新的Client容器,但可以基于已存在的Client容器來(lái)創(chuàng)建新的Client容器我是moore,大家一起加油!
標(biāo)簽: 提供數(shù)據(jù)