Docker 存儲(chǔ)驅(qū)動(dòng)詳細(xì)介紹
Docker 存儲(chǔ)驅(qū)動(dòng)詳細(xì)介紹
最近做項(xiàng)目,期間對(duì)Docker 存儲(chǔ)驅(qū)動(dòng)不會(huì),于是在網(wǎng)上找資料,并解決了,這里就記錄下。
目的
- 理解docker的存儲(chǔ)方式
- docker的image和container在host上的目錄結(jié)構(gòu)
- docker image和container的內(nèi)容與配置不同存儲(chǔ)
Docker是一個(gè)開源的應(yīng)用容器引擎,主要利用Linux內(nèi)核namespace實(shí)現(xiàn)沙盒隔離,用Cgroup實(shí)現(xiàn)資源限制。Docker用于統(tǒng)一開發(fā)和部署的輕量級(jí) Linux 容器,試圖解決“依賴地獄”問題,把依賴的服務(wù)和組件組合起來,類似船舶使用的集裝箱,達(dá)到快速安裝部署。
1. Docker的基本架構(gòu)—Client和Daemon
讓我們先搞明白docker的基本架構(gòu)和啟動(dòng)過程,其實(shí)Docker 采用了C/S架構(gòu),包括客戶端和服務(wù)端。Docker daemon作為服務(wù)端接受來自客戶的請(qǐng)求,并處理這些請(qǐng)求(創(chuàng)建、運(yùn)行、提交容器)。 客戶端和服務(wù)端在一個(gè)機(jī)器上,通過RESTful API 來進(jìn)行通信。 具體到使用的過程中,就是在執(zhí)行 service docker start 后,在主機(jī)(host)上產(chǎn)生docker deamon守護(hù)進(jìn)程,在后臺(tái)運(yùn)行并等待接收來自客戶端的消息(即輸入的docker命令,如 docker pull xxx,docker run …,docker commit xxx ),實(shí)現(xiàn)跟docker deamon的交互。當(dāng)啟動(dòng)docker服務(wù)后,可以看到docker進(jìn)程。
Default
[root@localhost ~]# ps -aux | grep docker root 11701 0.0 0.4 359208 16624 ? Ssl 21:05 0:00 /usr/bin/docker -d -H fd:// --selinux-enabled --insecure-registry 186.100.8.216:5000 root 11861 0.0 0.0 113004 2256 pts/0 S+ 23:01 0:00 grep --color=auto docker
說明這個(gè),主要是后面指定文件系統(tǒng)的時(shí)候,需要先在 /etc/sysconfig/docker 的配置具體的storage driver(這個(gè)會(huì)寫一篇專門的Blog),然后再啟動(dòng)Docker Daemon,而不能通過run命令的參數(shù)進(jìn)行操作。還可以直接在host命令行通過 docker –d 進(jìn)行設(shè)置。
2. Docker的存儲(chǔ)方式—Storage Driver
Docker模型的核心部分是有效利用分層鏡像機(jī)制,鏡像可以通過分層來進(jìn)行繼承,基于基礎(chǔ)鏡像(沒有父鏡像),可以制作各種具體的應(yīng)用鏡像。不同 Docker 容器就可以共享一些基礎(chǔ)的文件系統(tǒng)層,同時(shí)再加上自己獨(dú)有的改動(dòng)層,大大提高了存儲(chǔ)的效率。其中主要的機(jī)制就是分層模型和將不同目錄掛載到同一個(gè)虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem,來自 這篇文章 )。 針對(duì)鏡像存儲(chǔ)docker采用了幾種不同的存儲(chǔ)drivers,包括:aufs,devicemapper,btrfs 和overlay(來自 官網(wǎng) )。下面簡(jiǎn)單對(duì)不同的存儲(chǔ)drivers做個(gè)介紹。
AUFS
AUFS(AnotherUnionFS)是一種聯(lián)合文件系統(tǒng)。 AUFS 支持為每一個(gè)成員目錄(類似 Git 的分支)設(shè)定只讀(readonly)、讀寫(readwrite)和寫出(whiteout-able)權(quán)限, 同時(shí) AUFS 里有一個(gè)類似分層的概念, 對(duì)只讀權(quán)限的分支可以邏輯上進(jìn)行增量地修改(不影響只讀部分的)。AUFS唯一一個(gè)storage driver可以實(shí)現(xiàn)容器間共享可執(zhí)行及可共享的運(yùn)行庫(kù), 所以當(dāng)你跑成千上百個(gè)擁有相同程序代碼或者運(yùn)行庫(kù)時(shí)時(shí)候,AUFS是個(gè)相當(dāng)不錯(cuò)的選擇。
Device mapper
Device mapper 是 Linux 2.6 內(nèi)核中提供的一種從邏輯設(shè)備到物理設(shè)備的映射框架機(jī)制,在該機(jī)制下,用戶可以很方便的根據(jù)自己的需要制定實(shí)現(xiàn)存儲(chǔ)資源的管理策略( 詳見 ) 。Device mapper driver 會(huì)創(chuàng)建一個(gè)100G的簡(jiǎn)單文件包含你的鏡像和容器,每一個(gè)容器被限制在10G大小的卷內(nèi)(注意:這是利用loopback自動(dòng)創(chuàng)建的稀疏文件,具體為 /var/lib/docker/devicemapper/devicemapper 下的data和metadata,可動(dòng)態(tài)擴(kuò)張)??梢哉{(diào)整Docker容器的大小, 具體參考 ) 你可以在啟動(dòng)docker daemon時(shí)用參數(shù)-s 指定driver,也就是可以 docker -d -s devicemapper 設(shè)置docker的存儲(chǔ)driver。先關(guān)閉docker服務(wù),執(zhí)行命令:
Default
[root@localhost ~]# docker -d -s devicemapper INFO[0000] +job serveapi(unix:///var/run/docker.sock) INFO[0000] Listening for HTTP on unix (/var/run/docker.sock) INFO[0000] +job init_networkdriver() INFO[0000] -job init_networkdriver() = OK (0) INFO[0000] Loading containers: start. .... INFO[0000] Loading containers: done. INFO[0000] docker daemon: 1.4.0 4595d4f/1.4.0; execdriver: native-0.2; graphdriver: devicemapper INFO[0000] +job acceptconnections() INFO[0000] -job acceptconnections() = OK (0)
另外,docker在啟動(dòng)容器的時(shí)候可以指定 –storage-opt 參數(shù),但是現(xiàn)在只有devicemapper能夠接受參數(shù)設(shè)置。后面會(huì)有針對(duì)性的Blog展示。
BTRFS
Btrfs Driver 在docker build可以很高效。但是跟 devicemapper 一樣不支持設(shè)備間共享存儲(chǔ)(參加 官網(wǎng) )。Btrfs 支持創(chuàng)建快照(snapshot)和克隆(clone),還能夠方便的管理多個(gè)物理設(shè)備。(詳細(xì)了解可以參考 IBM對(duì)Btrfs的介紹 )
overlay
overlay跟AUFS很像,但是性能比AUFS好,有很好內(nèi)存利用,現(xiàn)在已經(jīng)合并入Linux內(nèi)核3.18了。具體使用命令: docker –d –s overlay
官網(wǎng)的Note: It is currently unsupported on btrfs or any Copy on Write filesystem and should only be used over ext4 partitions.
3 Docker目錄結(jié)構(gòu)
Docker兩個(gè)最重要的概念是鏡像和容器。那么我們pull下來的鏡像的存儲(chǔ)在哪里呢?鏡像運(yùn)行容器啟動(dòng)后,我們的操作修改的內(nèi)容存儲(chǔ)在哪里呢?因?yàn)榫唧w的驅(qū)動(dòng)不同,所以最終的實(shí)現(xiàn)效果不同。下面我們以Device Mapper存儲(chǔ)driver為例,分析下docker的存儲(chǔ)結(jié)構(gòu)。
1. 進(jìn)入 /var/lib/docker 目錄,列出內(nèi)容:
Default
[root@localhost ~]# cd /var/lib/docker/ [root@localhost docker]# ls containers devicemapper execdriver graph init linkgraph.db repositories-devicemapper tmp trust volumes
根據(jù)目錄的內(nèi)容,可以明顯的看到是使用了devicemapper driver。
注:以下顯示的文件夾都是在/var/lib/docker下的。
2. pull的鏡像文件存在哪個(gè)文件夾下呢?( 參考 )
pull的鏡像信息保存在了graph文件夾下,鏡像的內(nèi)容存在了 devicemapper/ devicemapper/data 下。
3. 啟動(dòng)的容器運(yùn)行在哪里呢?
啟動(dòng)的容器配置信息保存在 containers 里,查看了還有 execdriver/native/ 。
容器里操作的內(nèi)容保存在 devicemapper/devicemapper/data 下。
4. graph的角色
在Docker架構(gòu)中扮演已下載容器鏡像的保管者,以及已下載容器鏡像之間關(guān)系的記錄者。graph的本地目錄中,關(guān)于每一個(gè)的容器鏡像,具體存儲(chǔ)的信息有:該容器鏡像的元數(shù)據(jù)(json),容器鏡像的大?。╨ayersize)信息,以及該容器鏡像所代表的具體rootfs。
5. 實(shí)驗(yàn)測(cè)試:
- 初始沒有啟容器:
Default
[root@localhost docker]# ll containers/ total 0
- 啟動(dòng)一個(gè)容器:
Default
[root@localhost docker]# docker run -i -t --rm centos:7 /bin/bash [root@187a8f9d2865 /]#
所啟動(dòng)的容器的 UUID=187a8f9d2865
- 啟動(dòng)容器前,查看查看/var/lib/docker/devicemapper/devicemapper/下文件的實(shí)際大小
Default
[root@bhDocker216 docker]# du -h devicemapper/devicemapper/* 2.1G devicemapper/devicemapper/data 3.5M devicemapper/devicemapper/metadata
- 在host的主機(jī)上查看
Default
[root@bhDocker216 docker]# ls containers/ 187a8f9d2865c2ac***91b981
查看啟動(dòng)的容器在UUID文件夾下面的內(nèi)容:
Default
[root@bhDocker216 containers]# ll 187a8f9d2865c2ac***91b981 total 24 -rw-------. 1 root root 273 Mar 5 23:59 187a8f9d2865***-json.log -rw-r--r--. 1 root root 1683 Mar 5 23:58 config.json -rw-r--r--. 1 root root 334 Mar 5 23:58 hostconfig.json -rw-r--r--. 1 root root 13 Mar 5 23:58 hostname -rw-r--r--. 1 root root 174 Mar 5 23:58 hosts -rw-r--r--. 1 root root 69 Mar 5 23:58 resolv.conf - 在啟動(dòng)的容器添加文件,并查看。
先在運(yùn)行的容器內(nèi)創(chuàng)建一個(gè)文件:
Default
[root@8a1e3ad05d9e /]# dd if=/dev/zero of=floppy.img bs=512 count=5760 5760+0 records in 5760+0 records out 2949120 bytes (2.9 MB) copied, 0.0126794 s, 233 MB/s
然后在/var/lib/docker/devicemapper/devicemapper/下查看文件:
Default
[root@bhDocker216 docker]# du -h devicemapper/devicemapper/* 5.5G devicemapper/devicemapper/data 4.6M devicemapper/devicemapper/metadata
這地方大小有點(diǎn)出入,是因?yàn)橄葓?zhí)行了 # dd if=/dev/zero of=test.txt bs=1M count=8000 ,創(chuàng)建一個(gè)8G大小的文件,由于太慢我終止了,但是可以明確的看到在運(yùn)行的容器里進(jìn)行操作,兩個(gè)文件夾都發(fā)生了改變(增加)。
- 查看graph,在只pull了一個(gè)鏡像(Ubuntu14.10)的情況下,里面出現(xiàn)了7個(gè)長(zhǎng)UUID命名的目錄,這是怎么來的呢?
用 docker images –tree 列出鏡像樹形結(jié)構(gòu),我們可以看到鏡像的分層存儲(chǔ)結(jié)構(gòu)。最終的Ubuntu(第7層)是基于第6層改動(dòng)的,即這種邏輯上的樹中第n層基于是第n-1層改動(dòng)的,n層依賴n-1層的image。第0層,大小為0,稱為base image。
- graph/UUID目錄下內(nèi)容是啥呢?
Default
[root@localhost graph]# ll 01bf15a18638145eb*** -h total 8.0K -rw-------. 1 root root 1.6K Mar 5 18:02 json -rw-------. 1 root root 9 Mar 5 18:02 layersize
查看layersize的內(nèi)容:數(shù)字表示層的大?。▎挝唬築)。 josn:保存了這個(gè)鏡像的元數(shù)據(jù)(如: size,architecture,config,container,**parent的UUID** 等等)。
- 查看devicemapper/devicemapper文件夾
有兩個(gè)文件夾 data 和 metadata ,其實(shí)device mapper driver是就是把 鏡像和容器的文件 都存儲(chǔ)在 **data** 這個(gè)文件內(nèi)。可以通過docker info查看data和metadata的大小。 另外可以用 du –h (上面有用到)查看這兩個(gè)稀疏文件的實(shí)際大小。
- execdriver
Default
[root@bhDocker216 docker]# ls execdriver/native/ 8a1e3ad05d9e66a455e683a2c***2437bdcccdfdfa //對(duì)里面的內(nèi)容進(jìn)行查看: [root@bhDocker216 8a1e3ad05d9e66a455e***]# ls container.json state.json
- volumes
沒有加-v參數(shù)的volumes是空的,經(jīng)測(cè)試如果啟動(dòng)容器增加加-v參數(shù),volumes文件夾下將顯示一個(gè)UUID,在host進(jìn)行全局搜索,只在volumes下找到了,跟鏡像和容器的UUID都沒有關(guān)系。
Default
[root@bhDocker216 docker]# find / -name 86eb77f9f5e25676f100***d5a
/var/lib/docker/volumes/86eb77f9f5e25676f100***d5a
//查看里面的內(nèi)容:
[root@bhDocker216 volumes]# ls 86eb77f9f5e25676f100***d5a
config.json
[root@bhDocker216 volumes]# cat 86eb77f9f5e25676f100***d5a /config.json
{"ID":"86eb77f9f5e25676f100a89ba727bc15185303236aae0dcf4c17223e37651d5a","Path":"/home/data","IsBindMount":true,"Writable":true}
文件夾作用表格性說明
做個(gè)總結(jié),整理一個(gè)表格,把/var/lib/docker下的不同文件夾作用說明下:

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
mybatis-plus讀取JSON類型的方法實(shí)現(xiàn)
這篇文章主要介紹了mybatis-plus讀取JSON類型的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Spring事件監(jiān)聽器之@EventListener原理分析
這篇文章主要介紹了Spring事件監(jiān)聽器之@EventListener原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Spring應(yīng)用拋出NoUniqueBeanDefinitionException異常的解決方案
這篇文章介紹了解決org.springframework.beans.factory.NoUniqueBeanDefinitionException異常的一些解決方案,從這些解決方案可以看出Spring框架的設(shè)計(jì)精妙,遇見此問題的朋友可以參考下該解決方案2021-06-06
使用springboot結(jié)合vue實(shí)現(xiàn)sso單點(diǎn)登錄
這篇文章主要為大家詳細(xì)介紹了如何使用springboot+vue實(shí)現(xiàn)sso單點(diǎn)登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
springboot如何開啟緩存@EnableCaching(使用redis)
在Spring Boot項(xiàng)目中集成Redis主要包括添加依賴到pom.xml、配置application.yml中的Redis連接參數(shù)、編寫配置類、在啟動(dòng)類上添加@EnableCaching注解以及測(cè)試接口的查詢和緩存驗(yàn)證等步驟,首先,需要在pom.xml中添加spring-boot-starter-data-redis依賴2024-11-11
JAVA 根據(jù)身份證計(jì)算年齡的實(shí)現(xiàn)代碼
這篇文章主要介紹了JAVA 根據(jù)身份證計(jì)算年齡的實(shí)例代碼及java根據(jù)出生日期獲得年齡的方法,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05
Spring中@PropertySource和@Value注解詳解
這篇文章主要介紹了Spring中@PropertySource和@Value注解詳解,@PropertySource注解可以方便和靈活的向Spring的環(huán)境容器(org.springframework.core.env.Environment Environment)中注入一些屬性,這些屬性可以在Bean中使用,需要的朋友可以參考下2023-11-11
SSM框架使用poi導(dǎo)入導(dǎo)出Excel的詳細(xì)方法
這篇文章主要介紹了SSM框架使用poi導(dǎo)入導(dǎo)出Excel,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

