1. 程式人生 > Docker入門教學 >rootfs 與容器技術

rootfs 與容器技術

回到我們在 Linux 的環境,執行我們的“容器”:

/root/test/container

我們是不是可以像虛擬機器中的作業系統一樣,在容器中“為非作歹”了呢?
那!當!然!不!行!啦!

1. 為什麼需要 rootfs

先忽略 Cgroup 機制。在容器中探索時,不知大家是否發現,/bin,/etc,/var ... 等等目錄下的內容,它們與宿主機的目錄完全一致。你在這些目錄裡的更改一樣會影響到宿主機。聰明的讀者一定發現了,我們建立程序的時候不是指定開啟 Mount Namespace 了嗎,為什麼不生效呢?

即使我們啟用了 Mount Namespace,但它需要手動指定掛載時才能生效,我們在程式碼中指定容器程序中的 /tmp

目錄使用空的記憶體盤掛載,所以我們在容器中訪問到的 /tmp 目錄是空的,與宿主機不一致的。

至於其他的目錄,因為我們也沒有指定掛載點變更,它們會直接使用宿主機的目錄。但理想狀態下,我們會希望,進入在一個新的容器後,它的所有檔案都應該儘可能與宿主機隔離,我們才能放心使用它。

實現起來也不算複雜,我們知道 Linux 的目錄結構都是從 / 開始的,如果我們製作一份 / 目錄,然後在容器程序啟動的時候將它切換掛載到容器的 /,就可以解決這個問題。而像這種完整包含根目錄的拷貝,我們稱呼它:rootfs。

2. 構建 rootfs

構建一個真正可用的 rootfs 的過程其實非常繁瑣,我們不需要了解它的細節,我們僅僅需要使用它基本的功能理解 rootfs 即可。
這裡我們使用的構建命令如下:

cd /root/test/
mkdir rootfs
# 為rootfs提供初始目錄結構和核心依賴庫
sudo rpm -ivh --nodeps --root /home/root/test/rootfs https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/Packages/centos-release-8.1-1.1911.0.9.el8.x86_64.rpm
# 為rootfs安裝vim 工具和gcc編譯環境
sudo dnf --installroot=/root/test/rootfs install vim gcc --nogpgcheck

3. 使用 rootfs

在 Linux 環境的 /root/test/ 目錄下,已經有一份打包好的 rootfs,我們直接使用它即可。

我們來探查一下它的目錄結構:

tree -L 1

發現它與宿主機的/目錄的結構一致, 因為它就是我們容器將要使用的/

下面我們讓我們的容器使用這個 rootfs,編寫一個 helloworld 程式

Tip: 下面我們會使用到 chroot, chroot 是在 unix 系統的一個操作,針對正在運作的軟體行程和它的子程序,改變它外顯的根目錄。一個執行在這個環境下,經由 chroot 設定根目錄的程式,它不能夠對這個指定根目錄之外的檔案進行訪問動作,不能讀取,也不能更改它的內容。Namespace Mount 事實上就是受到 chroot 的啟發改進而來的。

cd /root/test/

## 執行容器環境
./container

## chroot切換到rootfs
chroot /root/rootfs /bin/bash

# 進入容器中的home目錄,編寫程式碼 helloworld.c並編譯執行
cd /home
vim helloworld.c
#include <stdio.h>
int main()
{
   // printf() 中字串需要引號
   printf("Hello, World!");
   return 0;
}

儲存後編譯執行

cc helloworld.c -o helloworld
./helloworld

我們將看到終端中顯示:

hello, world!

這樣我們獲得了一個檔案系統目錄與宿主機隔離的環境,在這裡,我們可以放心大膽地操作,不用擔心影響到宿主機的環境。

至此,我們獲取了一個可以使用 C 語言編譯執行應用的容器。

4. 拓展思考

如果 多個專案同時使用這個容器,他們之間如何隔離檔案系統呢?
直接拷貝或者重新構建多個 rootfs 似乎可行,但這浪費了空間

如果 容器使用過程中,不小心誤刪了某個 rootfs 中的關鍵檔案,導致容器被損壞, 怎麼辦?
讓 rootfs 的關鍵檔案設定為只讀的狀態,似乎可以解決這個問題。

如果我們想與其他人分享我們的容器和容器內的應用,該怎麼辦呢?
平臺相同的情況下,我們把 rootfs 和容器程序檔案拷貝一份副本給他們就行了。傳輸方式?U 盤,網盤,通訊軟體好像都可以。

如果…?

5. 小結

本節我們學習了容器場景下的 rootfs 需求的認知和構建使用。需要注意的是,rootfs只是一個作業系統所包含的檔案、配置和目錄,並不包括作業系統核心,因此在容器中執行的核心與宿主機一致,與核心相關的模組是無法隔離的。

結合前兩節中 Namespace 和 CGroup 的內容,我們對容器技術的核心概念和原理應該具有了充分的理解。但技術在產品化的過程中,比如拓展思考的部分,僅僅腦補就會遇到無數的問題,我們自己的解決方案似乎問題也很大,所以閉門造車是不行的,容器技術的核心部分將講到這裡,下面的章節就讓主角 Docker 正式登場。