在 Cgroup
和 Namespace
的管理下,容器其實是一個隔離和限制的 子系統
,那麼容器的文件系統又是如何隔離開來的呢?
Chroot 命令
chroot : 改變進程的根目錄到你指定的 的位置
# 將 /bin/bash進程的根目錄指定爲 /leon0204/home
# 執行 ls 將顯示 /leon0204/home 下的文件
$ chroot /leon0204/home /bin/bash
對於 /bin/bash
來說,它的根目錄就改變了,這種修改視圖的方法和namespace 是一個原理。
Rootfs
上節我們已經知道,容器啓動的是一個父進程和N個 fork 出來的子進程
,並且這個父進程被 chroot
修改了視圖,所以容器的根目錄就是一個隔離的子目錄,爲了讓這個目錄看起來更像一個系統,往往會在這個目錄下增加一些 系統的文件、目錄和配置
,比如 /bin
,/etc
等。
rootfs
即是容器鏡像的本身,是一個操作系統所包含的文件,配置和目錄,並不包括操作系統內核,在Linux系統開機時,需要加載系統內核,那麼一個鏡像的rootfs沒有了 內核
,如何正常加載呢?
由於 docker
的內核是建立在 宿主機
上的,與宿主機共享內核,記住:docker 沒有自己的內核
。所以 docker
的rootfs
實際上打包的不只是應用,而是整個 操作系統
,即應用運行的所有的依賴,而不是從語言層面上的依賴。這樣解決了跨機器的環境同步問題。
Layer 按層發佈
A同事發佈一個JAVA應用,會包含了一個操作系統的rootfs ,B同事發佈一個JAVA應用同樣需要製作一個 rootfs ,如何提取我們之間的 共性
?製造出一個基礎的鏡像(base image
)?
docker 在這方面實現上,引入了 layer
(層) 的概念,在A和B 製作 rootfs docker
鏡像系統的時候,把每一步
記錄下來,作爲一個 層
,取AB rootfs 的交集形成我們 JAVA base 鏡像
,以後我們發佈各自的應用都可以使用這個鏡像。
UFS
聯合文件系統 UFS Union File System
。UnionFS
:功能是將多個不同的目錄 unoin mount
到一個目錄下,比如A和B目錄的文件可以聯合掛載到C目錄下。這樣 A&B下的文件就和C形成了掛載,同步
增減改變。
AUFS
AUFS
是對 Union FS 的重寫和改進的版本,這也是 docker
使用的版本,以 Mysql:5.6
的鏡像爲例子,查看這個鏡像(rootfs)的AUFS結構如下:
[root@macco-web ~]# docker image inspect mysql:5.6
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:9c2f1836d49346677f8280bf0eb89c20853f6af4aa6e2fad87b0000bb181fad2",
"sha256:fd3b39222ee496a3cc115a4142a26babcad2f2008f4053ad5f893fcc503cd7fe",
"sha256:7ffd9f004dec5b25c7861e97e8f4ed5534f980b270fe03d0b834c0e6db843564",
"sha256:c782fd1b83e9e2b2a904c57cb887b59fd58704712ad73452de817abbd2d766a8",
"sha256:db76afa2e4c2f4c0077d028f37d73a6408cf2fc4bca1b0156225edd02f7e5cbc"
]
},
可以看到這個 docker 是由 5
個 layer
(層
)組成的,每一層實際上就是 系統的一個組成部分,包含了文件和目錄
,在使用的時候使用 AUFS 掛載
組成了鏡像rootfs
子系統,我們查看這個目錄下有哪些文件:
# pwd
/statics/docker/overlay/f8611219ff61896ca3ac0edc4e1c2207f934da81492c901b7768d115896f8cab/root
# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
總結
容器通過 aufs
爲 docker
創建出了一個完整的 rootfs linux
文件系統,也就是我們說的一個容器鏡像。
而鏡像又通過 layer 層
分層設計,將鏡像的設計變成了增量式的,使得協作的base 變得更小,協作的方式變得更迅捷,而每個人都是用 base 鏡像
,使得容器 一致性
得以實現。
Namespace做隔離;Cgroups做限制;Rootfs做子系統