Alpine?Distroless?Busybox?到底誰才是容器映象的瑞士軍刀?

原文連結:https://mp。weixin。qq。com/s/wW3Qaz7vERjAEHd9yzChZA

大多數情況下,我們構建容器映象時選擇的基礎映象無外乎是

busybox

alpine

google/distroless

這幾種,這幾個基礎映象在雲原生的世界很吃香,被廣泛應用於各個應用的容器化。

那麼問題來了,為什麼這幾個基礎映象如此受歡迎呢?

我們先來看下這幾個基礎映象的大小:

→ podman image ls REPOSITORY TAG IMAGE ID CREATED SIZEdocker。io/library/alpine latest 14119a10abf4 6 days ago 5。87 MBdocker。io/library/busybox latest 42b97d3c2ae9 13 days ago 1。46 MBgcr。io/distroless/static latest e0851a4aa136 51 years ago 3。06 MB

可以看到這些映象的體積都非常小,幾乎可以忽略不計。

Busybox

先啟動一個 Busybox 容器進去一探究竟:

Alpine?Distroless?Busybox?到底誰才是容器映象的瑞士軍刀?

這個映象的大小隻有

1。24MB

,卻容納了這麼多 GNU 命令,麻雀雖小五臟俱全啊,這到底是怎麼做到的?

事實上這一切都要歸功於

Multi-Call binary

。什麼是

Multi-Call binary

呢?

顧名思義,Multi-Call binary 就是

多重呼叫二進位制檔案

,是一個用C語言編寫的程式,它允許多次呼叫來執行二進位制檔案。它包含了很多函式,每個執行獨特動作的函式都可以透過一個名字來呼叫,這個名字同時也是 Multi-Call binary 的一個符號連結。Multi-Call binary 最好的應用範例便是 Busybox。

Busybox 裡面的函式可以透過兩種方式來呼叫:

busybox ls

ls

例如:

Alpine?Distroless?Busybox?到底誰才是容器映象的瑞士軍刀?

很明顯,這些不是我們所熟知的 GNU 二進位制檔案,因為所有的二進位制檔案都具有相同的屬性,比如大小、日期等。這些都不是獨立的二進位制檔案,而是 Multi-Call binary 每個呼叫函式的別名。這個 Multi-Call binary 就叫

Busybox

遺憾的是,這些 Busybox 命令並不完全等同於 GNU 命令,某些命令的某些引數是無法執行的,相當於閹割版。

Alpine

看完了 Busybox,我們再來看看 Alpine 是怎麼做的。

Alpine?Distroless?Busybox?到底誰才是容器映象的瑞士軍刀?

巧了,Alpine 的二進位制檔案竟然是指向 busybox 二進位制檔案的,這就很明顯了,Alpine 映象的底層使用了 busybox 二進位制檔案。除此之外,Alpine 還包含了

apk

包管理器和一些額外的可執行檔案,所以 Alpine 映象的體積才會比 Busybox 大。

Distroless

Distroless

就不用說了,它來自

Google

[1]。該映象幾乎就是空的,只包含應用程式及其執行時所需的依賴,不包含軟體包管理器、shell 和其他 GNU 二進位制檔案,當然還包含一些時區配置和部分 ca-certificates。

Alpine?Distroless?Busybox?到底誰才是容器映象的瑞士軍刀?

可以看到這個映象中有沒有

shell

也沒有

bash

,為了一探究竟,可以先把映象儲存為 tar 包,然後把

rootfs

解壓出來:

→ mkdir image → tar xvf distroless。tar。gz -C image/16679402dc206c982b5552ab8de7d898547100e5468be29d4f67d393c0eadfdb。tare0851a4aa13657fc8dcd01e0e5e08cb817123ccb82e2c604b34f9ec9c1755e3f。json2e18de03719583329b7fa8374130e57cc7cddf2b5a487fe4a4988622ca60575c/layer。tar2e18de03719583329b7fa8374130e57cc7cddf2b5a487fe4a4988622ca60575c/VERSION2e18de03719583329b7fa8374130e57cc7cddf2b5a487fe4a4988622ca60575c/jsonmanifest。jsonrepositories → cd image → ls -lhtotal 3。0M-r——r——r——。 1 root root 3。0M Jan 1 1970 16679402dc206c982b5552ab8de7d898547100e5468be29d4f67d393c0eadfdb。tardrwxr-xr-x。 2 root root 50 Sep 3 17:42 2e18de03719583329b7fa8374130e57cc7cddf2b5a487fe4a4988622ca60575c-r——r——r——。 1 root root 462 Jan 1 1970 e0851a4aa13657fc8dcd01e0e5e08cb817123ccb82e2c604b34f9ec9c1755e3f。json-r——r——r——。 1 root root 213 Jan 1 1970 manifest。json-r——r——r——。 1 root root 106 Jan 1 1970 repositories → mkdir rootfs → tar xf 16679402dc206c982b5552ab8de7d898547100e5468be29d4f67d393c0eadfdb。tar -C rootfs → tree rootfsrootfs├── bin├── boot├── dev├── etc│ ├── debian_version│ ├── default│ ├── dpkg│ │ └── origins│ │ └── debian│ ├── group│ ├── host。conf│ ├── issue│ ├── issue。net│ ├── nsswitch。conf│ ├── os-release│ ├── passwd│ ├── profile。d│ ├── protocols│ ├── rpc│ ├── services│ ├── skel│ ├── ssl│ │ └── certs│ │ └── ca-certificates。crt│ └── update-motd。d│ └── 10-uname├── home│ └── nonroot├── lib├── proc├── root├── run├── sbin├── sys├── tmp├── usr│ ├── bin│ ├── games│ ├── include│ ├── lib│ │ └── os-release│ ├── sbin│ │ └── tzconfig│ ├── share│ │ ├── base-files│ │ │ ├── dot。bashrc│ │ │ ├── dot。profile│ │ │ ├── dot。profile。md5sums│ │ │ ├── info。dir│ │ │ ├── motd│ │ │ ├── profile│ │ │ ├── profile。md5sums│ │ │ └── staff-group-for-usr-local……

該映象只有一層,大小為 3MB,也沒有二進位制檔案,只有一些證書檔案和目錄。如果向下滾動,還能看到許可證和時區配置。看來 Distroless 採取的是非常極端的手段,直接把不需要的二進位制檔案全部拋棄了,只留下一個空映象和部分必需品。

總結

由此看來,這幾個基礎映象如此受歡迎的主要原因就是體積小。映象越小,漏洞就越少,可攻擊面也會大幅減少,而且很容易維護。所以大家構建映象時儘量選擇這些映象作為基礎映象。

引用連結

[1]Google:

https://github。com/GoogleContainerTools/distroless