Skip to content

Commit 0d4666b

Browse files
committed
add docker image and env
1 parent bc3de9c commit 0d4666b

File tree

11 files changed

+153
-65
lines changed

11 files changed

+153
-65
lines changed

README.md

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,14 @@
11
# go-docker
22
> 用go写一个docker
33
4-
**注意**
4+
## 环境配置
5+
- 开发环境: windows
6+
- 运行环境: CentOS
7+
8+
### windows中goland配置
59
> windows下要修改goland的OS环境为 linux,不然只会引用`exec_windows.go`而不会引用`exec_linxu_go`
610
> 在Setting->Go->Build Tags & Vendoring -> OS=linux
711
8-
## namespace
9-
- uts : 隔离主机名
10-
- pid : 隔离进程pid
11-
- user : 隔离用户
12-
- network : 隔离网络
13-
- mount : 隔离挂载点
14-
- ipc : 隔离System VIPC和POSIX message queues
15-
16-
## cgroup
17-
> 主要是使用三个组件相互协作实现的,分别是:subsystem, hierarchy, cgroup,
18-
19-
- cgroup: 是对进程分组管理的一种机制
20-
- subsystem: 是一组资源控制的模块
21-
- hierarchy: 把一组cgroup串成一个树状结构(可让其实现继承)
22-
23-
### 实现方式
24-
> 主要实现方式是在`/sys/fs/cgroup/` 文件夹下,根据限制的不同,创建一个新的文件夹即可,kernel会将这个文件夹
25-
> 标记为它的`子cgroup`, 比如要限制内存使用,则在`/sys/fs/cgroup/memory/` 下创建`test-limit-memory`文件夹即可,将
26-
> 内存限制数写到该文件夹里面的 `memory.limit_in_bytes`即可
27-
28-
29-
## 环境配置
3012
### 设置CentOS支持aufs
3113
查看是否支持
3214
```bash
@@ -50,6 +32,67 @@ grub2-mkconfig -o /boot/grub2/grub.cfg
5032
# 重启计算机
5133
reboot
5234
```
35+
### 配置busybox
36+
```bash
37+
# 下载 busybox
38+
docker pull busybox
39+
# 运行
40+
docker run -d busybox top -b
41+
# 导出
42+
docker export -o busybox.tar (容器ID)
43+
# 解压到 /root文件夹下
44+
cd /root
45+
mkdir busybox
46+
tar -xvf busybox.tar -C busybox/
47+
```
48+
49+
## 使用指南
50+
```bash
51+
# 编译
52+
go build .
53+
54+
# 启动一个容器
55+
./go-docker run -ti --name test sh
56+
57+
# 后台启动
58+
./go-docker run -d --name test sh
59+
60+
# 进入容器
61+
./go-docker exec test sh
62+
63+
# 查看容器日志
64+
./go-docker logs test
65+
66+
# 查看容器列表
67+
./go-docker ps
68+
69+
# 停止容器
70+
./go-docker stop test
71+
72+
# 删除容器
73+
./go-docker rm test
74+
```
75+
76+
## docker核心技术
77+
### namespace
78+
- uts : 隔离主机名
79+
- pid : 隔离进程pid
80+
- user : 隔离用户
81+
- network : 隔离网络
82+
- mount : 隔离挂载点
83+
- ipc : 隔离System VIPC和POSIX message queues
84+
85+
### cgroup
86+
> 主要是使用三个组件相互协作实现的,分别是:subsystem, hierarchy, cgroup,
87+
88+
- cgroup: 是对进程分组管理的一种机制
89+
- subsystem: 是一组资源控制的模块
90+
- hierarchy: 把一组cgroup串成一个树状结构(可让其实现继承)
91+
92+
#### 实现方式
93+
> 主要实现方式是在`/sys/fs/cgroup/` 文件夹下,根据限制的不同,创建一个新的文件夹即可,kernel会将这个文件夹
94+
> 标记为它的`子cgroup`, 比如要限制内存使用,则在`/sys/fs/cgroup/memory/` 下创建`test-limit-memory`文件夹即可,将
95+
> 内存限制数写到该文件夹里面的 `memory.limit_in_bytes`即可
5396
5497
## 指令小记
5598

command.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ var runCommand = cli.Command{
4545
Name: "name",
4646
Usage: "container name",
4747
},
48+
cli.StringSliceFlag{
49+
Name: "e",
50+
Usage: "docker env",
51+
},
4852
},
4953
Action: func(ctx *cli.Context) error {
5054
if len(ctx.Args()) < 1 {
@@ -57,22 +61,26 @@ var runCommand = cli.Command{
5761
CpuShare: ctx.String("cpushare"),
5862
}
5963
// cmdArray 为容器运行后,执行的第一个命令信息
60-
// cmdArray[0] 为命令内容, 后面的为命令参数
64+
// cmdArray[0] 为镜像名, .Tail() 是去掉第一个后的全部参数
6165
var cmdArray []string
62-
for _, arg := range ctx.Args() {
66+
for _, arg := range ctx.Args().Tail() {
6367
cmdArray = append(cmdArray, arg)
6468
}
6569

6670
tty := ctx.Bool("ti")
67-
volume := ctx.String("v")
6871
detach := ctx.Bool("d")
6972

7073
if tty && detach {
7174
return fmt.Errorf("ti and d paramter can not both provided")
7275
}
7376

7477
containerName := ctx.String("name")
75-
Run(cmdArray, tty, res, volume, containerName)
78+
volume := ctx.String("v")
79+
// 要运行的镜像名
80+
imageName := ctx.Args().Get(0)
81+
envs := ctx.StringSlice("e")
82+
83+
Run(cmdArray, tty, res, containerName, imageName, volume, envs)
7684
return nil
7785
},
7886
}
@@ -124,7 +132,7 @@ var logCommand = cli.Command{
124132
return fmt.Errorf("missing container name")
125133
}
126134
containerName := ctx.Args().Get(0)
127-
container.LookContainerName(containerName)
135+
container.LookContainerLog(containerName)
128136
return nil
129137
},
130138
}

common/common.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package common
33
const (
44
RootPath = "/root/"
55
MntPath = "/root/mnt/"
6-
BusyBox = "busybox"
7-
BusyBoxTar = "busybox.tar"
86
WriteLayer = "writeLayer"
97
)
108

container/exec.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package container
22

33
import (
4+
"fmt"
5+
"io/ioutil"
46
"os"
57
"os/exec"
68
"strings"
@@ -24,7 +26,25 @@ func ExecContainer(containerName string, cmdArray []string) {
2426
cmd.Stderr = os.Stderr
2527
err = os.Setenv(common.EnvExecPid, info.Pid)
2628
err = os.Setenv(common.EnvExecCmd, strings.Join(cmdArray, " "))
29+
// 设置环境变量
30+
envs := getEnvsByPid(info.Pid)
31+
cmd.Env = append(os.Environ(), envs...)
32+
2733
if err = cmd.Run(); err != nil {
2834
logrus.Errorf("exec cmd run, err: %v", err)
2935
}
3036
}
37+
38+
func getEnvsByPid(pid string) []string {
39+
envFilePath := fmt.Sprintf("/proc/%s/environ", pid)
40+
file, err := os.Open(envFilePath)
41+
if err != nil {
42+
logrus.Errorf("open env file, path: %s, err: %v", envFilePath, err)
43+
return nil
44+
}
45+
bs, err := ioutil.ReadAll(file)
46+
if err != nil {
47+
logrus.Errorf("read env file, err: %v", err)
48+
}
49+
return strings.Split(string(bs), "\u0000")
50+
}

container/info.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type ContainerInfo struct {
2424
Status string `json:"status"`
2525
}
2626

27+
// 记录容器信息
2728
func RecordContainerInfo(containerPID int, cmdArray []string, containerName, containerID string) error {
2829
info := &ContainerInfo{
2930
Pid: strconv.Itoa(containerPID),

container/log.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import (
1111
"go-docker/common"
1212
)
1313

14-
func LookContainerName(containerName string) {
14+
// 查看容器内日志信息
15+
func LookContainerLog(containerName string) {
1516
logFileName := path.Join(common.DefaultContainerInfoPath, containerName, common.ContainerLogFileName)
1617
file, err := os.Open(logFileName)
1718
if err != nil {

container/process.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
)
1313

1414
// 创建一个会隔离namespace进程的Command
15-
func NewParentProcess(tty bool, volume, containerName string) (*exec.Cmd, *os.File) {
15+
func NewParentProcess(tty bool, volume, containerName, imageName string, envs []string) (*exec.Cmd, *os.File) {
1616
readPipe, writePipe, _ := os.Pipe()
1717
// 调用自身,传入 init 参数,也就是执行 initCommand
1818
cmd := exec.Command("/proc/self/exe", "init")
@@ -40,10 +40,13 @@ func NewParentProcess(tty bool, volume, containerName string) (*exec.Cmd, *os.Fi
4040
}
4141
cmd.Stdout = file
4242
}
43+
// 设置额外文件句柄
4344
cmd.ExtraFiles = []*os.File{
4445
readPipe,
4546
}
46-
err := NewWorkSpace(common.RootPath, common.MntPath, volume)
47+
// 设置环境变量
48+
cmd.Env = append(os.Environ(), envs...)
49+
err := NewWorkSpace(volume, containerName, imageName)
4750
if err != nil {
4851
logrus.Errorf("new work space, err: %v", err)
4952
}

container/remove.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"go-docker/common"
1010
)
1111

12+
// 删除容器
1213
func RemoveContainer(containerName string) {
1314
info, err := getContainerInfo(containerName)
1415
if err != nil {

0 commit comments

Comments
 (0)