gpt4 book ai didi

docker - 从零开始的容器说明

转载 作者:行者123 更新时间:2023-12-01 21:13:25 26 4
gpt4 key购买 nike

我正在学习有关容器,尤其是docker的知识。我刚刚看了这段Liz Rice的视频,其中她从头开始创建了一个容器(repo在github.com/lizrice上)。我不完全了解它,因为我是Docker和容器的新手,而且我不懂Go编程语言。但是,我想看看是否有人可以快速解释一下代码中的这些项目/正在努力实现的目标:

package main

import (
"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))
}

func cg() {
cgroups := "/sys/fs/cgroup/"
pids := filepath.Join(cgroups, "pids")
os.Mkdir(filepath.Join(pids, "liz"), 0755)
must(ioutil.WriteFile(filepath.Join(pids, "liz/pids.max"), []byte("20"), 0700))
// Removes the new cgroup in place after the container exits
must(ioutil.WriteFile(filepath.Join(pids, "liz/notify_on_release"), []byte("1"), 0700))
must(ioutil.WriteFile(filepath.Join(pids, "liz/cgroup.procs"), []byte(strconv.Itoa(os.Getpid())), 0700))
}

func must(err error) {
if err != nil {
panic(err)
}
}

特别是,我对容器的理解是,它是一个虚拟的运行时环境,用户可以在其中将应用程序与基础系统隔离,并且容器只是在单个主机上运行的隔离的进程组,它们满足一组“通用”要求特征。我对容器是什么有一个很好的认识,并希望从更广泛的意义上说要实现,但是我想帮助您理解这样的特定示例。如果有人对此很了解-导入块中正在导入什么;主要职能是什么情况?语句在run函数中的用途是什么,子函数和cg函数将完成什么工作?

我认为,以我目前的理解并阅读Docker教程,再从头开始对真实代码进行解释,将非常有益。只是要确认-此代码与Docker本身无关,在代码之外创建了一个容器,而Docker是一项使创建容器更容易的技术。

最佳答案

她通过执行以下操作来创建一种容器:

  • 她将执行main.go并在容器
  • 中传递要执行的命令
  • 为此,她运行一个执行run()函数
  • 的进程
    她在run()函数中使用
  • 来准备要 fork 的过程,该过程将执行child()函数
  • ,但在实际 fork 之前,通过syscall.SysProcAttr,她为以下各项配置了新的 namespace :
  • “unix时间共享”(syscall.CLONE_NEWUTS),这实际上将允许子进程
  • 中具有单独的主机名
  • PID(syscall.CLONE_NEWPID),以便在她正在创建的“容器”中拥有从1
  • 开始的新PID
  • 挂载(syscall.CLONE_NEWNS)将使“容器”具有单独的挂载
  • 接下来她执行fork(cmd.Run())

  • 在 fork 的过程中,child()函数在此处执行:
  • 她通过cg()准备了一个控制组,该组将限制“容器”可用的资源,这是通过在/ sys / fs / cgroup /
  • 中写入一些适当的文件来完成的
  • 接下来,她使用传递给main.go的args准备要执行的命令
  • 她使用chroot到/ home / liz / ubuntufs下的新根目录
  • 她monuts特殊的fs proc和另一个临时的fs
  • 最后,她执行作为参数提供给main.go的命令

  • containers from scratch视频中,她很好地介绍了所有这些内容。
    她在那里在容器中执行bash,以查看新的PID,具有新的主机名并限制为20个进程。

    为了使其正常工作,她需要/ home / liz / ubuntufs下的完整ubuntu fs克隆。

    带回家的3个关键点是,一个容器(以及她的“容器”)基本上是这样做的:
  • 使用 namespace 定义容器将在以下方面看到的内容
    PID /挂接(在此容器示例中,她未处理联网)
  • 使用chroot将容器限制为文件系统
  • 的一部分
  • 使用cgroups限制资源,容器可以使用
  • 关于docker - 从零开始的容器说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62210179/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com