您好,登錄后才能下訂單哦!
一、Docker底層存儲機制介紹
對于Docker來講,它作為容器運行的底層引擎,在組織和運行其容器時,每個容器內運行一個程序及子程序,容器啟動時依賴于底層可能不止一層的只讀鏡像聯合掛載啟動而成。它底層能夠存儲此類分層構建并聯合掛載鏡像的文件系統包含AUFS、Overlayfs2、devmapper文件系統。最后一定要在最上層構建一個可寫層。對于此可寫層來說,所有在容器中所執行的寫操作(對數據的修改、對內容的修改),都是保存在最上層的可寫層。對下層內容的增刪改操作我們需要使用“寫時復制”(COW)機制來實現
寫時復制機制是;如果一個文件在最底層是存在的,在任意層中被標記為刪除,那么用戶最上層就看不到這個文件了。用戶能看到的只能是沒被標記為刪除的或者被標記為刪除而用戶在最上層又自己創建了同名的文件。
對于這種方式來說,我們去訪問一個文件(修改刪除等一類的操作),在訪問和使用時,效率會非常的低。尤其是那些對I/O要求較高的應用比如redis、mysql。如mysql本身就對I/O要求就較高,如果mysql運行又是將數據寫在容器內的聯合掛載的最上層的可寫層文件系統上,那么在容器停止時,數據將被刪除。而且在實現數據存取時其效率的低下也是必然的情形。要想繞過這種使用的限制,我們可以通過使用存儲卷的機制來實現。
二、存儲卷介紹
所謂存儲卷可以簡單想象成在特權級的名稱空間(宿主機)當中找一個本地文件系統之上存在某一個目錄,把這個目錄直接與容器內部的文件系統之上的某一個目錄建立綁定關系,隨后,容器內的進程向這個目錄中寫數據時,是直接被寫在宿主機的目錄上的,這和使用mount --bind命令的功能非常相似,這樣就使得我們容器內部進程在實現數據保存時,能繞過容器內部文件系統的限制,從而與宿主機的文件系統建立了關聯關系。這使得我們可以在宿主機和容器內共享數據和內容。可以讓我們的容器直接訪問宿主機的內容。同樣的,也可以讓宿主機直接向容器供給內容。這就相當于說讓兩個本來是隔離的mount名稱空間在某個子路徑上建立一定程度的綁定關系,從而使得在兩個容器之間的文件系統的某個子路徑上不在是隔離的,而且能夠實現共享的效果。這種關聯關系能夠讓容器之間在跨文件系統共享數據時,變得容易了,而在宿主機上的這個目錄(與容器內的文件系統建立綁定關系的)對于容器來說,就被稱作volume(存儲卷)。存儲卷帶來的好處是當容器關閉甚至是刪除時。我們都不用 擔心數據丟書了,只要不刪除綁定的在宿主機上的目錄(存儲卷)就可以。隨后再次重建這個容器時,我們能讓它關聯到同一個存儲卷上,就可以使用相同的數據。因此就能夠數據持久脫離容器的生命周期而持久。
docker默認的存儲卷是在本地的宿主機的文件系統之上,如果容器要在多個docker host之間遷移(使用docker 集群),我們還可以添加共享存儲,如NFS文件系統使得容器內的有狀態應用可以將遷移變的容易
2.1、容器內的文件系統存在的問題
關閉并重啟容器,其數據不受影響,但刪除容器,將同時刪除容器數據
存儲于聯合掛載文件系統中,不易于宿主機訪問
容器間數據共享不便
2.2、volume的好處
volume的初衷是獨立于容器的生命周期實現數據持久化,因此刪除容器時,不會刪除其數據,也不會對未被引用的卷做垃圾回收工作。因此我們使用存儲卷就是為了解決容器內的聯合掛載文件系統所帶來的問題。
2.3、volume的種類
Docker有兩種類型的卷,每種類型都在容器中存在一個掛載點,但在宿主機上的位置有所不同
Bind mount volume:在宿主機和容器內的路徑需要人工分別指定一個特定路徑,兩個已知路徑建立綁定關系
docker run --name web1 -it -v HOSTDIR:VOLUMEDIR nginx:latest
Docker managed volume:只需要在容器內指定容器內的掛載點是哪里,而被綁定的是宿主機上的哪個路徑下的目錄由Docker的daemon自行創建一個空目錄或者使用一個已存在的目錄與存儲卷建立綁定關系。這種方式在第一次啟動容器時非常方便,他會自動為容器在宿主機上的一個路徑下創建volumen,但是在該容器刪除且重新啟動時,它有可能會重新生成一個新的volume。
docker run --name web1 -it -v /data nginx:latest
三、Docker容器使用volume
3.1、docker managed volume
1、通過-v /data指定了myweb容器的volume。
[root@bogon ~]# docker container run -d -v /data --rm --name myweb httpd:1.1 54b7acd21f2a8bafeaa9bf2653828a54be0c8190fb53216423e9aca6f1da6be4 [root@bogon ~]# [root@bogon ~]# docker container exec -it myweb /bin/sh sh-4.1# ls bin boot data dev etc home lib lib64 lost+found media mnt opt proc root sbin selinux srv sys tmp usr var sh-4.1#
2、查看容器的詳細信息
可以看到Mounts中volume的掛載點是/data,在宿主機上的位置等信息
[root@bogon ~]# docker container inspect myweb [ "Mounts": [ { "Type": "volume", "Name": "0905db81948a0d09d2c1f811eb113a72356f7d73e6085e0b513e6fcabd26dc1b", "Source": "/var/lib/docker/volumes/0905db81948a0d09d2c1f811eb113a72356f7d73e6085e0b513e6fcabd26dc1b/_data", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], "ArgsEscaped": true, "Image": "httpd:1.1", "Volumes": { "/data": {} } ]
3、在宿主機上向掛載點目錄寫入數據后在容器內驗證
[root@bogon ~]# cd /var/lib/docker/volumes/0905db81948a0d09d2c1f811eb113a72356f7d73e6085e0b513e6fcabd26dc1b/_data [root@bogon _data]# ls index.html [root@bogon ~]# docker container exec -it myweb /bin/sh sh-4.1# ls /data/ index.html [root@bogon _data]# echo "welcome to my container." >hello.html [root@bogon _data]# ls hello.html index.html [root@bogon ~]# docker container exec -it myweb /bin/sh sh-4.1# ls /data/ hello.html index.html sh-4.1# cat /data/hello.html welcome to my container.
4、在容器內刪除volume中的文件
[root@bogon ~]# docker container exec -it myweb /bin/sh sh-4.1# rm -f /data/hello.html sh-4.1# ls /data/ index.html [root@bogon _data]# ls index.html
5、刪除容器后重新啟動驗證文件是否存在
[root@bogon _data]# docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 54b7acd21f2a httpd:1.1 "/usr/sbin/apachectl?? 23 minutes ago Up 23 minutes 5000/tcp myweb [root@bogon _data]# docker container kill myweb myweb [root@bogon _data]# docker container rm myweb Error: No such container: myweb [root@bogon _data]# docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [root@bogon _data]# [root@bogon _data]# docker container run -it -v /data --name myweb2 httpd:1.1 /bin/sh sh-4.1# ls /data/ index.html sh-4.1# cat /data/index.html <h2>Welcom To My Httpd</h2>
3.2、Bind mount volume
綁定卷的功能和docker managed volume的功能一樣,只不過在啟動容器時需要同時指定宿主機的路徑和容器內的路徑
[root@bogon myweb3]# docker container inspect myweb3 [ "Mounts": [ { "Type": "bind", "Source": "/data/volumes/myweb3", "Destination": "/data/httpd/index", "Mode": "", "RW": true, "Propagation": "rprivate" } ], } ] [root@bogon myweb3]# [root@bogon _data]# docker container run -d -v /data/volumes/myweb3/:/data/httpd/index/ --name myweb3 httpd:1.1 c5828deffb5b8413c80841b3f2e9675565f7f20125311778df5c3123d867f07f [root@bogon _data]# [root@bogon _data]# ll /data/volumes/myweb3/ total 0 sh-4.1# [root@bogon ~]# docker container exec -it myweb3 /bin/sh sh-4.1# ls /data/httpd/index/ sh-4.1#
在宿主機的路徑創建文件后驗證容器內是否存在
[root@bogon myweb3]# echo 333 >hello.html [root@bogon myweb3]# cat hello.html 333 sh-4.1# ls /data/httpd/index/ hello.html sh-4.1# cat /data/httpd/index/hello.html 333
3.3、容器間的數據共享
通過將兩個容器使用同一個宿主機的目錄,可以實現容器間的數據共享
在啟動一個容器叫myweb4
[root@bogon myweb3]# docker container run -d -v /data/volumes/myweb3/:/data/httpd/index/ --name myweb4 httpd:1.1 e9b6509c14436e8b23c45cadd447bab00f61f871525a07907563d09c807ef4e3 [root@bogon myweb3]# docker container exec -it myweb4 /bin/sh sh-4.1# cd /data/httpd/index/ sh-4.1# cat hello.html 333
這種方式可以讓多個容器間共享數據
3.4、通過復制其他容器的卷設置來啟動新的容器,讓多個容器間共享數據
[root@bogon myweb3]# docker container run -d --name myweb5 --volumes-from myweb4 httpd:1.1 24b378251586371aade5232ba55ed16ba093ea5800c80562ae3863ab694f2116 [root@bogon myweb3]# [root@bogon myweb3]# [root@bogon myweb3]# docker container inspect -f {{.Mounts}} myweb5 [{bind /data/volumes/myweb3 /data/httpd/index true rprivate}]
通過復制其他容器的卷設置來啟動新的容器,為我們省掉了每次啟動新容器都需要指定很長的volume路徑,我們也可以制作一個底層基礎支撐容器叫basedcontainer,這個容器不需要運行,根據這個底層基礎支撐容器,我們可以隨意的組合一個架構,比如啟動nginx、mysql、tomcat這三個容器,這三個容器都使用--network container:basedcontainer 加入這個底層基礎支撐容器的網絡,并且使用--volumes-from來使用這個基礎容器的卷設置。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。