1、Docker底層存儲機制介紹
html
對於Docker來說,它做爲容器運行的底層引擎,在組織和運行其容器時,每一個容器內運行一個程序及子程序,容器啓動時依賴於底層可能不止一層的只讀鏡像聯合掛載啓動而成。它底層可以存儲此類分層構建並聯合掛載鏡像的文件系統包含AUFS、Overlayfs二、devmapper文件系統。最後必定要在最上層構建一個可寫層。對於此可寫層來講,全部在容器中所執行的寫操做(對數據的修改、對內容的修改),都是保存在最上層的可寫層。對下層內容的增刪改操做咱們須要使用「寫時複製」(COW)機制來實現
mysql
寫時複製機制是;若是一個文件在最底層是存在的,在任意層中被標記爲刪除,那麼用戶最上層就看不到這個文件了。用戶能看到的只能是沒被標記爲刪除的或者被標記爲刪除而用戶在最上層又本身建立了同名的文件。linux
對於這種方式來講,咱們去訪問一個文件(修改刪除等一類的操做),在訪問和使用時,效率會很是的低。尤爲是那些對I/O要求較高的應用好比redis、mysql。如mysql自己就對I/O要求就較高,若是mysql運行又是將數據寫在容器內的聯合掛載的最上層的可寫層文件系統上,那麼在容器中止時,數據將被刪除。並且在實現數據存取時其效率的低下也是必然的情形。要想繞過這種使用的限制,咱們能夠經過使用存儲卷的機制來實現。nginx
2、存儲卷介紹web
所謂存儲卷能夠簡單想象成在特權級的名稱空間(宿主機)當中找一個本地文件系統之上存在某一個目錄,把這個目錄直接與容器內部的文件系統之上的某一個目錄創建綁定關係,隨後,容器內的進程向這個目錄中寫數據時,是直接被寫在宿主機的目錄上的,這和使用mount --bind命令的功能很是類似,這樣就使得咱們容器內部進程在實現數據保存時,能繞過容器內部文件系統的限制,從而與宿主機的文件系統創建了關聯關係。這使得咱們能夠在宿主機和容器內共享數據和內容。可讓咱們的容器直接訪問宿主機的內容。一樣的,也可讓宿主機直接向容器供給內容。這就至關於說讓兩個原本是隔離的mount名稱空間在某個子路徑上創建必定程度的綁定關係,從而使得在兩個容器之間的文件系統的某個子路徑上不在是隔離的,並且可以實現共享的效果。這種關聯關係可以讓容器之間在跨文件系統共享數據時,變得容易了,而在宿主機上的這個目錄(與容器內的文件系統創建綁定關係的)對於容器來講,就被稱做volume(存儲卷)。存儲卷帶來的好處是當容器關閉甚至是刪除時。咱們都不用 擔憂數據丟書了,只要不刪除綁定的在宿主機上的目錄(存儲卷)就能夠。隨後再次重建這個容器時,咱們能讓它關聯到同一個存儲捲上,就可使用相同的數據。所以就可以數據持久脫離容器的生命週期而持久。redis
docker默認的存儲卷是在本地的宿主機的文件系統之上,若是容器要在多個docker host之間遷移(使用docker 集羣),咱們還能夠添加共享存儲,如NFS文件系統使得容器內的有狀態應用能夠將遷移變的容易sql
2.一、容器內的文件系統存在的問題docker
關閉並重啓容器,其數據不受影響,但刪除容器,將同時刪除容器數據
apache
存儲於聯合掛載文件系統中,不易於宿主機訪問
tomcat
容器間數據共享不便
2.二、volume的好處
volume的初衷是獨立於容器的生命週期實現數據持久化,所以刪除容器時,不會刪除其數據,也不會對未被引用的卷作垃圾回收工做。所以咱們使用存儲卷就是爲了解決容器內的聯合掛載文件系統所帶來的問題。
2.三、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
3、Docker容器使用volume
3.一、docker managed volume
一、經過-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#
二、查看容器的詳細信息
能夠看到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": {} } ]
三、在宿主機上向掛載點目錄寫入數據後在容器內驗證
[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.
四、在容器內刪除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
五、刪除容器後從新啓動驗證文件是否存在
[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 <h1>Welcom To My Httpd</h1>
3.二、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.三、容器間的數據共享
經過將兩個容器使用同一個宿主機的目錄,能夠實現容器間的數據共享
在啓動一個容器叫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.四、經過複製其餘容器的卷設置來啓動新的容器,讓多個容器間共享數據
[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來使用這個基礎容器的卷設置。