1. 准备工作
1.1 准备环境
root@nicktming:~/go/src/github.com/nicktming/mydocker# git clone https://github.com/nicktming/mydocker.git
root@nicktming:~/go/src/github.com/nicktming/mydocker# git checkout code-5.7.2
root@nicktming:~/go/src/github.com/nicktming/mydocker# git checkout -b dev-5.8
1.2 准备busybox.tar
// 前提条件
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar
2. 实现
2.1 增加环境变量参数
增加环境变量参数
e
.
var RunCommand = cli.Command{
Name: "run",
Flags: []cli.Flag {
...
cli.StringSliceFlag{
Name: "e",
Usage: "set environment",
},
...
},
Action: func(c *cli.Context) error {
...
envSlice := c.StringSlice("e")
...
Run(command, tty, &cg, rootPath, volumes, containerName, imageName, envSlice)
return nil
},
}
2.2 修改Run方法
func Run(command string, tty bool, cg *cgroups.CroupManger, rootPath string, volumes []string, containerName, imageName string, envSlice []string) {
...
cmd := exec.Command(initCmd, "init")
cmd.Env = append(os.Environ(), envSlice...)
...
}
将增加的环境变量放入到容器中.
2.3 测试
// -it 的形式没有问题
root@nicktming:~/go/src/github.com/nicktming/mydocker# go build .
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -e name=nicktming busybox /bin/sh
2019/04/19 22:44:30 rootPath is empaty, set rootPath: /nicktming
2019/04/19 22:44:30 current path: /nicktming/mnt/15556850702382348471.
/ # env | grep name
name=nicktming
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
// 后台运行
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -d -name container01 -e name=nicktming busybox /bin/top
2019/04/19 23:03:28 rootPath is empaty, set rootPath: /nicktming
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker exec container01 /bin/sh
2019/04/19 23:03:43 containerName:container01,command:/bin/sh
/ # env | grep name
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
后台运行的容器再次进入容器的时候发现得不到环境变量. 这是因为
exec
本身启动的是另外一个进程, 只不过与后台的那个进程拥有相同的namespace
. 具体可以参考[mydocker]---实现进入容器Namespace. 由于环境变量是继承自父进程的,所以exec
命令启动的那个进程是继承自宿主机的, 因此在exec 进程内看到的环境变量其实是宿主机的环境变量.
2.4 增加exec命令获得环境变量
func Exec(containerName, command string) {
...
containerEnvs := getEnvsByPid(containerInfo.Pid)
cmd.Env = append(os.Environ(), containerEnvs...)
...
}
func getEnvsByPid(pid string) []string {
path := fmt.Sprintf("/proc/%s/environ", pid)
contentBytes, err := ioutil.ReadFile(path)
if err != nil {
log.Printf("Read file %s error %v", path, err)
return nil
}
envs := strings.Split(string(contentBytes), "\u0000")
return envs
}
由于进程存放环境变量的位置是
/proc/<PID >/environ
, 因此根据给定的PID 去读取这个文件,便可以获取环境变量。在文件的内容中,每个环境变量之间是通过\u0000
分割的,因此以此为标记来获取环境变量数组。
2.5 测试后台容器
root@nicktming:~/go/src/github.com/nicktming/mydocker# go build .
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker ps
ID NAME PID STATUS COMMAND CREATED
15556862082746239371 container01 3176 running /bin/top 2019-04-19 23:03:28
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker exec container01 /bin/sh
2019/04/19 23:17:00 containerName:container01,command:/bin/sh
/ # env | grep name
name=nicktming
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
3. 参考
1. 自己动手写docker.(基本参考此书,加入一些自己的理解,加深对
docker
的理解)
4. 全部内容
mydocker.png
1. [mydocker]---环境说明
2. [mydocker]---urfave cli 理解
3. [mydocker]---Linux Namespace
4. [mydocker]---Linux Cgroup
5. [mydocker]---构造容器01-实现run命令
6. [mydocker]---构造容器02-实现资源限制01
7. [mydocker]---构造容器02-实现资源限制02
8. [mydocker]---构造容器03-实现增加管道
9. [mydocker]---通过例子理解存储驱动AUFS
10. [mydocker]---通过例子理解chroot 和 pivot_root
11. [mydocker]---一步步实现使用busybox创建容器
12. [mydocker]---一步步实现使用AUFS包装busybox
13. [mydocker]---一步步实现volume操作
14. [mydocker]---实现保存镜像
15. [mydocker]---实现容器的后台运行
16. [mydocker]---实现查看运行中容器
17. [mydocker]---实现查看容器日志
18. [mydocker]---实现进入容器Namespace
19. [mydocker]---实现停止容器
20. [mydocker]---实现删除容器
21. [mydocker]---实现容器层隔离
22. [mydocker]---实现通过容器制作镜像
23. [mydocker]---实现cp操作
24. [mydocker]---实现容器指定环境变量
25. [mydocker]---网际协议IP
26. [mydocker]---网络虚拟设备veth bridge iptables
27. [mydocker]---docker的四种网络模型与原理实现(1)
28. [mydocker]---docker的四种网络模型与原理实现(2)
29. [mydocker]---容器地址分配
30. [mydocker]---网络net/netlink api 使用解析
31. [mydocker]---网络实现
32. [mydocker]---网络实现测试
网友评论