docker作為一個容器平台,它有一套自己的存儲系統。它支持的driver有overlay,overlay2, aufs等等。
這篇文章主要分析overlay和overlay2的區別。
overlay
啟動docker,刪除本地所有的鏡像。進入/var/lib/docker/overlay目錄,可以看到此時這個目錄下面什么都沒有,是空的。
然后按照下面的Dockerfile制作一個鏡像:
[root@localhost ~]# echo aa>>aa
[root@localhost ~]# echo bb>>bb
[root@localhost ~]# echo cc>>cc
[root@localhost ~]# cat Dockerfile
FROM ubuntu
COPY aa /
COPY bb /
COPY cc /
[root@localhost ~]# docker build -t aabbcc .
Sending build context to Docker daemon 478.8 MB
Step 1/4 : FROM ubuntu
---> 7698f282e524
Step 2/4 : COPY aa /
---> cb97dcb8731f
Removing intermediate container 894ff7c4e4bb
Step 3/4 : COPY bb /
---> f073ea1ca7f3
Removing intermediate container 857c5cf0e128
Step 4/4 : COPY cc /
---> 9ace6ecb0953
Removing intermediate container e2a682d5cd56
Successfully built 9ace6ecb0953
上面的一系列操作制作了一個名字為aabbcc的image。此時可以在/var/lib/docker/overlay 下面觀察到新的層已經生成了。這里每copy一個文件就會生成新的一層。
下面的代碼框中紅色標記的部分就是我們copy了三個文件, aa, bb,cc所生成的三層。
[root@localhost overlay]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE aabbcc latest 9ace6ecb0953 14 hours ago 69.9 MB docker.io/ubuntu latest 7698f282e524 4 weeks ago 69.9 MB [root@localhost overlay]# docker history aabbcc IMAGE CREATED CREATED BY SIZE COMMENT 9ace6ecb0953 14 hours ago /bin/sh -c #(nop) COPY file:a79ff676c1e17f... 3 B f073ea1ca7f3 14 hours ago /bin/sh -c #(nop) COPY file:77c3ff995e3afe... 3 B cb97dcb8731f 14 hours ago /bin/sh -c #(nop) COPY file:f17d63ff0a8d89... 3 B 7698f282e524 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B <missing> 4 weeks ago /bin/sh -c mkdir -p /run/systemd && echo '... 7 B <missing> 4 weeks ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0 B <missing> 4 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' >... 745 B <missing> 4 weeks ago /bin/sh -c #(nop) ADD file:1f4fdc61e133d2f... 69.9 MB [root@localhost overlay]#
觀察一下/var/lib/docker/overlay/目錄。aa文件出現了三次,bb文件出現了兩次,cc文件只出現了一次,這也與我們拷貝它們的順序相吻合。
層級結構一目了然。
[root@localhost overlay]# ls cfd414e52a3b25dade86fb2333d5cd84bb0632e55872914e42c0510cf7c211ea/root/
aa bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@localhost overlay]# ls 5b42d020f1bc93d2643e67c6fe7d86f3a20efd80767bf505853dd743d8b51a31/root/
aa bb bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@localhost overlay]# ls 00e5e192b42ad8923eda7d43016c56864fdb0c22c239cb141140c9959d138400/root/
aa bb bin boot cc dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
再觀察一下幾個aa文件的inode號
[root@localhost overlay]# find . -name aa|xargs ls -i
1057923 ./00e5e192b42ad8923eda7d43016c56864fdb0c22c239cb141140c9959d138400/root/aa 1057923 ./cfd414e52a3b25dade86fb2333d5cd84bb0632e55872914e42c0510cf7c211ea/root/aa
1057923 ./5b42d020f1bc93d2643e67c6fe7d86f3a20efd80767bf505853dd743d8b51a31/root/aa
我們可以看到,這里aa實際上是通過硬鏈接的方式鏈到不同的層里的。下面,我們嘗試使用aabbcc運行一個容器。從中我們可以觀察到,多出了一個aa文件,這實際上就是容器真正運行的rootfs(bfa602b98523bcc9d311e39729f1b4fd8a5046d5856b3d153886a67373a0f9f9/merged)。
通過mount指令,我們可以觀察到內核將鏡像和upper掛載到了指定的rootfs中了。
[root@localhost overlay]# find . -name aa|xargs ls -i
1057923 ./00e5e192b42ad8923eda7d43016c56864fdb0c22c239cb141140c9959d138400/root/aa 1057923 ./bfa602b98523bcc9d311e39729f1b4fd8a5046d5856b3d153886a67373a0f9f9/merged/aa
1057923 ./5b42d020f1bc93d2643e67c6fe7d86f3a20efd80767bf505853dd743d8b51a31/root/aa 1057923 ./cfd414e52a3b25dade86fb2333d5cd84bb0632e55872914e42c0510cf7c211ea/root/aa
[root@localhost overlay]# mount|grep overlay
/dev/mapper/fedora-root on /var/lib/docker/overlay type ext4 (rw,relatime,seclabel)
overlay on /var/lib/docker/overlay/bfa602b98523bcc9d311e39729f1b4fd8a5046d5856b3d153886a67373a0f9f9/merged type overlay (rw,relatime,context="system_u:object_r:container_file_t:s0:c286,c1020",lowerdir=/var/lib/docker/overlay/00e5e192b42ad8923eda7d43016c56864fdb0c22c239cb141140c9959d138400/root,upperdir=/var/lib/docker/overlay/bfa602b98523bcc9d311e39729f1b4fd8a5046d5856b3d153886a67373a0f9f9/upper,workdir=/var/lib/docker/overlay/bfa602b98523bcc9d311e39729f1b4fd8a5046d5856b3d153886a67373a0f9f9/work)
[root@localhost overlay]# ls
總結一下,overlay對於每一層都會構築一個完整的鏡像,鏡像和鏡像之間通過硬鏈接共享文件。當啟動一個容器時,內核會union mount這個容器所
使用的鏡像所對應的layer(lowerdir)和一個讀寫層(upperdir),並且lowerdir只有一層。
overlay2
用同樣的Dockerfile構建一個叫aabbcc的image,觀察/var/lib/docker/overlay2下面的文件,我們可以看到各個文件只有一個。
[root@localhost overlay2]# find . -name aa
./6e3c65cf94f4775224ee352074375629e368daaf9061681b08d2f5ab31c96a6d/diff/aa
[root@localhost overlay2]# find . -name bb
./6dd8011792252dea81cf322244e2ec78ced101c5b40c4750025d7b1aef7856f1/diff/bb
[root@localhost overlay2]# find . -name cc
./503efa11453748cadb1eaa7c0a2dde817047568d5ff7c255d0dfac885be6d557/diff/cc
進入到cc所在layer中,可以看到里面有四個文件/文件夾,diff里面存儲了這一層所包含的文件,這里就只有cc這一個文件。link中存儲的是這一層所對應的/var/lib/docker/overlay2/l/中的軟連接。
lower文件中存儲的是這一層所依賴的低層。它們用冒號隔開,每一條記錄都是指向/var/lib/docker/overlay2/l/ 中的軟連接。
[root@localhost 503efa11453748cadb1eaa7c0a2dde817047568d5ff7c255d0dfac885be6d557]# ls
diff link lower work
[root@localhost 503efa11453748cadb1eaa7c0a2dde817047568d5ff7c255d0dfac885be6d557]# tree
.
├── diff
│ └── cc
├── link
├── lower
└── work
2 directories, 3 files
[root@localhost 503efa11453748cadb1eaa7c0a2dde817047568d5ff7c255d0dfac885be6d557]# cat link
JYJ3FGGMPXESBF7GQL72HXOXRV
[root@localhost 503efa11453748cadb1eaa7c0a2dde817047568d5ff7c255d0dfac885be6d557]# cat lower
l/C35GLEH6TWWOAX4BIZE6VT5KYG:l/7ODJACACJZTVZHL26VDQWAX3RS:l/2M2BNBIKMH7INTTHG2DVXM2YTM:l/2TH4LWHZM3V7UAVOSTQS6KY25A:l/52C2E2ZTZQUNS7YEWOIVT7RUOK
下面我們嘗試運行一個容器,然后觀察overlay2的掛載情況:
[root@localhost overlay2]# find . -name aa|xargs ls -i 921329 ./6e3c65cf94f4775224ee352074375629e368daaf9061681b08d2f5ab31c96a6d/diff/aa 921329 ./9151b049c61baa18cc19f2b2afddc12e08fac0f24af7f5d3a0f803a605482558/merged/aa [root@localhost overlay2]# mount|grep overlay overlay on /var/lib/docker/overlay2/9151b049c61baa18cc19f2b2afddc12e08fac0f24af7f5d3a0f803a605482558/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/MPGCJYXEJSAZHETJT64ETIGTZJ:/var/lib/docker/overlay2/l/JYJ3FGGMPXESBF7GQL72HXOXRV:/var/lib/docker/overlay2/l/C35GLEH6TWWOAX4BIZE6VT5KYG:/var/lib/docker/overlay2/l/7ODJACACJZTVZHL26VDQWAX3RS:/var/lib/docker/overlay2/l/2M2BNBIKMH7INTTHG2DVXM2YTM:/var/lib/docker/overlay2/l/2TH4LWHZM3V7UAVOSTQS6KY25A:/var/lib/docker/overlay2/l/52C2E2ZTZQUNS7YEWOIVT7RUOK,upperdir=/var/lib/docker/overlay2/9151b049c61baa18cc19f2b2afddc12e08fac0f24af7f5d3a0f803a605482558/diff,workdir=/var/lib/docker/overlay2/9151b049c61baa18cc19f2b2afddc12e08fac0f24af7f5d3a0f803a605482558/work)
從中可以看到,這個容器的rootfs是掛載到一個lowerdi為多層的rootfs上的。
總結
綜上所述,overlay實際上通過硬鏈接在層和層之間共享文件,而overlay2的每一層都是完全獨立的。如果容器啟動的話,它會將多層lowerdir 掛載到它的rootfs。
這種設計就會帶來一個問題,那就是linux系統會限制系統中硬鏈接的數量,如果用戶下載了很多容器,那么docker就會在系統中到處創建硬鏈接,達到最大值后將無法創建新容器。
因此,我們應該使用overlay2作為docker的graph driver而不是overlay