docker 容器开发

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

转载于:https://my.oschina.net/u/4038454/blog/3011317

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值