亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Container From Scratch 的解釋

Container From Scratch 的解釋

Go
catspeake 2022-06-06 18:03:30
我正在學習容器和碼頭工人。我剛剛觀看了這個 Liz Rice 視頻,其中她從頭開始創建了一個容器(repo 在 github.com/lizrice)。我無法完全遵循它,因為我是 Docker 和容器的新手,而且我不懂 Go 編程語言。但是,我想看看是否有人可以非??焖俚亟忉尨a中的這些項目是/試圖完成的內容:package mainimport (    "fmt"    "io/ioutil"    "os"    "os/exec"    "path/filepath"    "strconv"    "syscall")// go run main.go run <cmd> <args>func main() {    switch os.Args[1] {    case "run":        run()    case "child":        child()    default:        panic("help")    }}func run() {    fmt.Printf("Running %v \n", os.Args[2:])    cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)    cmd.Stdin = os.Stdin    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    cmd.SysProcAttr = &syscall.SysProcAttr{        Cloneflags:   syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,        Unshareflags: syscall.CLONE_NEWNS,    }    must(cmd.Run())}func child() {    fmt.Printf("Running %v \n", os.Args[2:])    cg()    cmd := exec.Command(os.Args[2], os.Args[3:]...)    cmd.Stdin = os.Stdin    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    must(syscall.Sethostname([]byte("container")))    must(syscall.Chroot("/home/liz/ubuntufs"))    must(os.Chdir("/"))    must(syscall.Mount("proc", "proc", "proc", 0, ""))    must(syscall.Mount("thing", "mytemp", "tmpfs", 0, ""))    must(cmd.Run())    must(syscall.Unmount("proc", 0))    must(syscall.Unmount("thing", 0))}特別是,我對容器的理解是,它是一個虛擬化的運行時環境,用戶可以在其中將應用程序與底層系統隔離開來,而容器只是運行在單個主機上的隔離進程組,它們實現了一組“通用”特征。我很清楚容器是什么,并試圖在更廣泛的意義上完成,但我希望幫助理解這樣的具體示例。如果有人很好地理解這一點 - 導入塊中正在導入什么;主要功能中的情況是什么;run 函數中的語句有什么用,child 和 cg 函數正在完成什么?我認為以我目前的理解和閱讀 Docker 教程,加上一個從頭開始的真實代碼示例的解釋將非常有益。只是為了確認 - 此代碼與 Docker 本身無關,除了代碼創建容器之外,Docker 是一種使創建容器更容易的技術。
查看完整描述

2 回答

?
千萬里不及你

TA貢獻1784條經驗 獲得超9個贊

她正在通過這樣做來創建一種容器:

  • 她將執行 main.go 并傳遞要在容器中執行的命令

  • 為此,她運行了一個執行 run() 函數的進程

  • 在 run() 函數中,她準備了一個要分叉的進程,該進程將執行 child() 函數

  • 但在實際分叉之前,通過 syscall.SysProcAttr,她配置了一個新的命名空間:

    • “unix 分時”(syscall.CLONE_NEWUTS)這本質上將允許在子進程中有一個單獨的主機名

    • PIDs (syscall.CLONE_NEWPID) 這樣在她正在創建的“容器”中,她將擁有從 1 開始的新 PID

    • mounts (syscall.CLONE_NEWNS) 將使“容器”擁有單獨的掛載

  • 接下來她執行 fork (cmd.Run())

在分叉的進程中,child() 函數在這里執行:

  • 她通過 cg() 準備了一個控制組,它將限制“容器”可用的資源,這是通過在 /sys/fs/cgroup/ 中編寫一些適當的文件來完成的

  • 接下來,她使用傳遞給 main.go 的 args 準備要執行的命令

  • 她使用 chroot 到 /home/liz/ubuntufs 下的新根目錄

  • 她monuts特殊fs proc和另一個臨時fs

  • 最后,她執行作為參數提供給 main.go 的命令

在從頭開始的視頻容器中,她很好地呈現了這一切。在那里,她在容器中執行了一個 bash,該容器看到了新的 PID,有一個新的主機名,并且限制為 20 個進程。

為了讓它工作,她需要在 /home/liz/ubuntufs 下有一個完整的 ubuntu fs 克隆。

要帶回家的 3 個關鍵點是容器(以及她的“容器”)本質上是這樣做的:

  • 使用命名空間來定義容器將看到的 PID/掛載(在這個容器示例中她沒有處理網絡)

  • 使用 chroot 將容器限制為文件系統的一部分

  • 使用 cgroups 來限制容器可以使用的資源


查看完整回答
反對 回復 2022-06-06
?
天涯盡頭無女友

TA貢獻1831條經驗 獲得超9個贊

由于我缺乏 GO 經驗以及對自定義 docker 容器的經驗有限,我無法確認此代碼的作用。

雖然這不是直接回答標題中的問題,但我想提供一個答案,幫助您學習 docker 的基礎知識以幫助您入門。

你對容器的理解是正確的。嘗試查找使用您熟悉的語言的更簡單示例的教程。

一個讓您入門的簡單示例是創建一個您喜歡的 linux 操作系統的容器,將 docker 容器附加到您當前的終端,然后在容器中運行一些特定于操作系統的命令(例如在容器中安裝軟件或任何 linux 命令)


查看完整回答
反對 回復 2022-06-06
  • 2 回答
  • 0 關注
  • 184 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號