package mainimport ( "fmt" "os" "os/exec" "os/user" "path/filepath" "strconv" "syscall")func main() { switch os.Args[1] { case "run": parent() case "child": child() default: panic("what should i do?") }}func parent() { cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...) cmd.SysProcAttr = &syscall.SysProcAttr{} cmd.SysProcAttr.Cloneflags = syscall.CLONE_NEWUSER | syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNET | syscall.CLONE_NEWNS cmd.SysProcAttr.Credential = &syscall.Credential{ Uid: 0, Gid: 0, } curuser, _ := user.Current() uid, _ := strconv.Atoi(curuser.Uid) gid, _ := strconv.Atoi(curuser.Gid) cmd.SysProcAttr.UidMappings = []syscall.SysProcIDMap{ {ContainerID: 0, HostID: uid, Size: 1}} cmd.SysProcAttr.GidMappings = []syscall.SysProcIDMap{ {ContainerID: 0, HostID: gid, Size: 1}} cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout if err := cmd.Run(); err != nil { panic(err) os.Exit(-1) }}func pivotRoot(root string) error { if err := syscall.Mount(root, root, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("Mount rootfs to itself error :v%", err) } pivotDir := filepath.Join(root, ".pivot_root") if _, err := os.Stat(pivotDir); os.IsNotExist(err) { if err := os.Mkdir(pivotDir, 0700); err != nil { return err } } if err := syscall.PivotRoot(root, pivotDir); err != nil { return fmt.Errorf("pivot_root %v", err) } os.Chdir("/home/") #容器启动后指定工作路径 pivotDir = filepath.Join("/", ".pivot_root") if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil { return fmt.Errorf("unmount pivot_root dir %v", err) } return nil}func child() { pwd, _ := os.Getwd() fmt.Println(pwd) rootfs := filepath.Join(pwd, "rootfs") fmt.Println(rootfs) if err := pivotRoot(rootfs); err != nil { fmt.Printf("Error runing pivot_root - %s \n", err) os.Exit(-1) } defaultMountFlags := syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV syscall.Mount("proc", "/proc", "proc", uintptr(defaultMountFlags), "") 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.Errorf("ERROR", err) os.Exit(-1) }}
参考:https://blog.csdn.net/quqi99/article/details/77931497