package main
import (
"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.youkuaiyun.com/quqi99/article/details/77931497