本项目构建测试环境基于Ubuntu 14.04.4,kernel版本是3.13.x,请先确认环境再提交issue
针对不同版本的系统或者kernel我们没做过兼容性的测试,可以提交PR一起来提高mydocker的兼容性。
known issue:
- 4.2+的内核中userns的使用方式变化导致operation not permitted: #3
- Centos 7.x中的内核不支持userns
- 4.4内核运行后会导致/proc挂载不释放,导致后续命令报错 #8
- Ubuntu 14.04.4之后的版本使用systemd去管理cgroup,会导致cgroup的限制失效
Pls check following command output: dpkg -l | grep linux-image-extra If the command output is empty, Pls install the package by command apt-get update; apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual.
O(∩_∩)O谢谢啊 你们的书让我受益匪浅。
看完想加入你们部门,但是看到封面折页上你们title才是高级,难道你们部门牛人挤成堆了么,有点吓人。我同学西欧小硕回来工作一年加入蚂蚁,第2年就P7了。
@2qif49lt 欢迎给我邮箱发简历,我的邮箱是[email protected] 。 我们努力的招贤纳士中,期待新鲜血液加入 :)
uname -a
Linux vagrant-ubuntu-trusty-64 3.13.0-112-generic #159-Ubuntu SMP Fri Mar 3 15:26:07 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
go run main.go
2018/03/17 16:33:21 fork/exec /bin/sh: operation not permitted
exit status 1
package main
import (
"log"
"os"
"os/exec"
"syscall"
)
func main() {
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER,
}
cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(1), Gid: uint32(1)}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
@rhinoceros Pls run with root account or use sudo.
@BSWANG 我是在mac上用vagrant启动的虚拟机。多谢答复。 修改成这样就好了。
package main
import (
"log"
"os"
"os/exec"
"syscall"
)
func main() {
cmd := exec.Command("sh")
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS |
syscall.CLONE_NEWUSER |
syscall.CLONE_NEWNET,
UidMappings: []syscall.SysProcIDMap{
{
ContainerID: 1234,
HostID: 0,
Size: 1,
},
},
GidMappings: []syscall.SysProcIDMap{
{
ContainerID: 1234,
HostID: 0,
Size: 1,
},
},
}
//cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(1), Gid: uint32(1)}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
需要安装的包有:
环境相关
apt-get install git -y
apt-get install stress -y
apt-get install cgroup-bin cgroup-lite libcgroup1 -y
Go (我用了 go1.9.2,书里推荐 1.7.1 )
wget https://studygolang.com/dl/golang/go1.9.2.linux-amd64.tar.gz
tar -C /usr/local -xzf /vagrant/go1.9.2.linux-amd64.tar.gz
vim /etc/profile
export GOPATH="/root/go"
export GOROOT="/usr/local/go"
export GOBIN="${GOROOT}/bin"
export PATH=$PATH:$GOBIN
source /etc/profile
# godep
go get github.com/tools/godep
第四章开始需要用到docker
install docker ce 17.03.1~ce-0~ubuntu-trusty
#!/bin/bash
set -e
type -f docker >/dev/null 2>&1 && { echo "docker is exists!"; exit 0; }
sudo apt-get update
sudo apt-get install -y linux-image-extra-$(uname -r) linux-image-extra-virtual
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install -y docker-ce=17.03.1~ce-0~ubuntu-trusty
# 配置一个国内docker镜像加速:
# 举例,镜像加速地址:https://aaaaaaaa.mirror.aliyuncs.com
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors" : [
"https://aaaaaaaa.mirror.aliyuncs.com"
]
}
EOF
service docker restart
sudo docker run hello-world
@rhinoceros 感谢
@xianlubird centos7.4 code-2.1:
command-line-arguments
./main.go:19: undefined: initCommand ./main.go:20: undefined: runCommand
什么问题???
netlink版本低
master 分支下,编译报错,vendor下的netlink版本低了,删了go get一个最新的编译可过
pivot_root报错
我的是ubuntu16,所以跑代码在pivot_root系统调用那里报错Invalid argument,然后程序退出后,/proc有问题,其他issue有提到,翻了下runc的代码,发现是因为/这个mount point的标记位是share, 所以pivot_root切换rootfs失败,加上后面重新mount /proc的时候,传递到host的/proc,使host的也有问题,在mount隔离下,是不应该有share的mount point的.
所以在pivotRoot函数开始加上
if err := syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil {
return fmt.Errorf("make parent mount private error: %v", err)
}
即
func pivotRoot(root string) error {
if err := syscall.Mount("", "/", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil {
return fmt.Errorf("make parent mount private error: %v", err)
}
/**
为了使当前root的老 root 和新 root 不在同一个文件系统下,我们把root重新mount了一次
bind mount是把相同的内容换了一个挂载点的挂载方法
*/
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)
}
// 创建 rootfs/.pivot_root 存储 old_root
pivotDir := filepath.Join(root, ".pivot_root")
if err := os.Mkdir(pivotDir, 0777); err != nil {
return err
}
// pivot_root 到新的rootfs, 现在老的 old_root 是挂载在rootfs/.pivot_root
// 挂载点现在依然可以在mount命令中看到
if err := syscall.PivotRoot(root, pivotDir); err != nil {
return fmt.Errorf("pivot_root %v", err)
}
// 修改当前的工作目录到根目录
if err := syscall.Chdir("/"); err != nil {
return fmt.Errorf("chdir / %v", err)
}
pivotDir = filepath.Join("/", ".pivot_root")
// umount rootfs/.pivot_root
if err := syscall.Unmount(pivotDir, syscall.MNT_DETACH); err != nil {
return fmt.Errorf("unmount pivot_root dir %v", err)
}
// 删除临时文件夹
return os.Remove(pivotDir)
}
问题解决,host的/proc也没问题了
希望遇到问题的人能看到啦
Ubuntu 14.04 没有cgroup on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory)
的可以试下安装docker,安装完成后就出现了.
但是指定docker版本,否则dockers run 报caused "process_linux.go:297: copying bootstrap data to pipe caused \"write init-p: broken pipe\"": unknown.
root@ubuntu:~# apt remove docker-ce docker-ce-cli
root@ubuntu:~# apt install docker-ce=18.06.1~ce~3-0~ubuntu
urfave/cli 用的是什么版本呢?
./mydocker run -ti -m 100m stress -m 1
urfave用的是1.22.4版本,然后发现 后面的 -m 1 被处理没了

@BSWANG 我是在mac上用vagrant启动的虚拟机。多谢答复。 修改成这样就好了。
package main import ( "log" "os" "os/exec" "syscall" ) func main() { cmd := exec.Command("sh") cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER | syscall.CLONE_NEWNET, UidMappings: []syscall.SysProcIDMap{ { ContainerID: 1234, HostID: 0, Size: 1, }, }, GidMappings: []syscall.SysProcIDMap{ { ContainerID: 1234, HostID: 0, Size: 1, }, }, } //cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(1), Gid: uint32(1)} cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatal(err) } }
谢谢我的问题和你一样,运行大半天出不来,把你的代码copy就好了,请问这是为什么?和虚拟机有声梦关系
谢谢
内核版本问题,3.19