前面的十几篇文章分别介绍了各种namespace和pivot_root的使用,下面将通过一个简单例子将他们组合成一个容器。首先还是和RUNC一样构建一个rootfs(docker export $(docker create busybox) | tar -C rootfs -xvf -)。在ubuntu 14.04系统上,编译并运行下面程序:
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
)
func main() {
switch os.Args[1] {
case "run":
parent()
case "child":
child()
default:
panic("wat should I do")
}
}
func parent() {
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("ERROR", err)
os.Exit(1)
}
}
func child() {
must(syscall.Mount("rootfs", "rootfs", "bind", syscall.MS_BIND|syscall.MS_REC, ""))
must(os.MkdirAll("rootfs/.oldrootfs", 0700))
must(syscall.PivotRoot("rootfs", "rootfs/.oldrootfs"))
must(os.Chdir("/"))
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("ERROR", err)
os.Exit(1)
}
}
func must(err error) {
if err != nil {
panic(err)
}
}
大部分代码之前文章分享的时候已经零散介绍了,这里只是组装了一下。但有个特殊的小细节:当执行run命令后,程序调用自己(/proc/self/exe指向程序本身)child命令重新执行并设置各种namespace,切换root目录,从而创建出一个新的容器。
页面更新:2024-05-17
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号