1. 准备工作
本文承接内容 [mydocker]---一步步实现volume操作 , 由于其实现会让多个容器共用容器层, 这样会导致多个容器之间的数据不隔离, 相互可以访问修改彼此之间的数据. 因此本文将会实现容器层隔离.
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.6
root@nicktming:~/go/src/github.com/nicktming/mydocker# git checkout -b dev-5.7
1.2 准备busybox.tar
// 前提条件
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar
1.3 预期效果
-----------------------------------------------terminal 01---------------------------------------------------------
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar
root@nicktming:/nicktming#
-----------------------------------------------terminal 02---------------------------------------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container01 -v /nicktming/volume1:/containerVolume busybox /bin/sh
2019/04/16 23:14:37 rootPath is empaty, set rootPath: /nicktming
2019/04/16 23:14:37 current path: /nicktming/mnt/container01.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 15:14 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 103 root root 0 Apr 16 15:14 proc
drwx------ 2 root root 4096 Apr 16 15:14 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # echo "container01:test01" > containerVolume/test01.txt
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
-----------------------------------------------terminal 03---------------------------------------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container02 -v /nicktming/volume2:/containerVolume busybox /bin/sh
2019/04/16 23:15:41 rootPath is empaty, set rootPath: /nicktming
2019/04/16 23:15:41 current path: /nicktming/mnt/container02.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 15:15 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 105 root root 0 Apr 16 15:15 proc
drwx------ 2 root root 4096 Apr 16 15:15 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # echo "container02:test01" > containerVolume/test01.txt
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
-----------------------------------------------terminal 01---------------------------------------------------------
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# cat volume1/test01.txt
container01:test01
root@nicktming:/nicktming# cat volume2/test01.txt
container02:test01
root@nicktming:/nicktming#
2. 命令行操作
以下操作基本遵循该图. 关于
AUFS
可以参考[mydocker]---通过例子理解存储驱动AUFS
图片.png
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar
root@nicktming:/nicktming# mkdir -p /nicktming/busybox && tar -xvf busybox.tar -C /nicktming/busybox
root@nicktming:/nicktming# mkdir mnt writerLayer
root@nicktming:/nicktming# ls
busybox busybox.tar mnt writerLayer
创建第一个容器container01
// 根据镜像busybox启动第一个容器container-01
root@nicktming:/nicktming# mkdir -p mnt/container01 writerLayer/container01
root@nicktming:/nicktming#
root@nicktming:/nicktming# mount -t aufs -o dirs=/nicktming/writerLayer/container01:/nicktming/busybox none /nicktming/mnt/container01
// 可以看到容器内部看到的文件结构如下
root@nicktming:/nicktming# ls -l /nicktming/mnt/container01/
total 48
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
// 映射volume 类似于: -v /nicktming/volume1:/containerVolume
root@nicktming:/nicktming# mkdir -p /nicktming/volume1 /nicktming/mnt/container01/containerVolume
root@nicktming:/nicktming# ls -l /nicktming/mnt/container01/
total 52
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 2 root root 4096 Apr 15 23:34 containerVolume
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming# mount -t aufs -o dirs=/nicktming/volume1 none /nicktming/mnt/container01/containerVolume
root@nicktming:/nicktming# ls -l /nicktming/mnt/container01/containerVolume/
total 0
root@nicktming:/nicktming# echo "container01:test01" > /nicktming/mnt/container01/containerVolume/test01.txt
// 查看宿主机内容volume1文件夹
root@nicktming:/nicktming# ls -l /nicktming/volume1/
total 4
-rw-r--r-- 1 root root 19 Apr 15 23:36 test01.txt
root@nicktming:/nicktming# cat /nicktming/volume1/test01.txt
container01:test01
root@nicktming:/nicktming#
类似的方法创建第二个容器
root@nicktming:/nicktming# mount -t aufs -o dirs=/nicktming/writerLayer/container02:/nicktming/busybox none /nicktming/mnt/container02
root@nicktming:/nicktming# mkdir -p /nicktming/mnt/container02/containerVolume
root@nicktming:/nicktming# ls -l /nicktming/mnt/container02/
total 52
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 2 root root 4096 Apr 15 23:51 containerVolume
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming# mount -t aufs -o dirs=/nicktming/volume2 none /nicktming/mnt/container02/containerVolume
root@nicktming:/nicktming# ls -l /nicktming/mnt/container02/containerVolume/
total 0
root@nicktming:/nicktming# echo "container02:test01" > /nicktming/mnt/container02/containerVolume/test01.txt
root@nicktming:/nicktming# cat /nicktming/mnt/container02/containerVolume/test01.txt
container02:test01
root@nicktming:/nicktming# ls -l volume2/
total 4
-rw-r--r-- 1 root root 19 Apr 15 23:53 test01.txt
root@nicktming:/nicktming# cat volume2/test01.txt
container02:test01
root@nicktming:/nicktming#
查看两个容器的内容
// 查看两个容器的内容
root@nicktming:/nicktming# ls -l mnt/
total 8
drwxr-xr-x 15 root root 4096 Apr 15 23:34 container01
drwxr-xr-x 15 root root 4096 Apr 15 23:51 container02
root@nicktming:/nicktming# ls -l mnt/container01
total 52
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Apr 15 23:36 containerVolume
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming# ls -l mnt/container02
total 52
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Apr 15 23:53 containerVolume
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming# cat mnt/container01/containerVolume/test01.txt
container01:test01
root@nicktming:/nicktming# cat mnt/container02/containerVolume/test01.txt
container02:test01
root@nicktming:/nicktming#
可以看到两个容器之间互不影响. 此时两个容器删除, 看看数据是不是已经被持久化, 并且镜像层
busybox
没有做任何改变.
// 删除容器container02
root@nicktming:/nicktming# umount /nicktming/mnt/container02/containerVolume
root@nicktming:/nicktming# umount /nicktming/mnt/container02
// 删除容器02后可以看到mnt/container02已经没有文件了
root@nicktming:/nicktming# ls -l mnt/
total 8
drwxr-xr-x 15 root root 4096 Apr 15 23:34 container01
drwxr-xr-x 2 root root 4096 Apr 15 23:47 container02
root@nicktming:/nicktming# ls -l mnt/container01
total 52
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Apr 15 23:36 containerVolume
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming# ls -l mnt/container02
total 0
// 删除容器container01
root@nicktming:/nicktming# umount /nicktming/mnt/container01/containerVolume
root@nicktming:/nicktming# umount /nicktming/mnt/container01
root@nicktming:/nicktming# ls -l mnt/
total 8
drwxr-xr-x 2 root root 4096 Apr 15 23:29 container01
drwxr-xr-x 2 root root 4096 Apr 15 23:47 container02
root@nicktming:/nicktming# ls -l mnt/container01
total 0
root@nicktming:/nicktming# ls -l mnt/container02
total 0
// 查看宿主机的内容 可以看到持久化的内容已经存在
root@nicktming:/nicktming# ls
busybox busybox.tar mnt volume1 volume2 writerLayer
root@nicktming:/nicktming# ls -l volume1
total 4
-rw-r--r-- 1 root root 19 Apr 15 23:36 test01.txt
root@nicktming:/nicktming# ls -l volume2
total 4
-rw-r--r-- 1 root root 19 Apr 15 23:53 test01.txt
root@nicktming:/nicktming# cat volume1/test01.txt
container01:test01
root@nicktming:/nicktming# cat volume2/test01.txt
container02:test01
root@nicktming:/nicktming#
// 可以看到镜像层没有任何改变
root@nicktming:/nicktming# ls -l busybox
total 48
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
// 查看容器层 已经没有什么作用 可以删除
root@nicktming:/nicktming# ls -l writerLayer/
total 8
drwxr-xr-x 5 root root 4096 Apr 15 23:34 container01
drwxr-xr-x 5 root root 4096 Apr 15 23:51 container02
root@nicktming:/nicktming# rm -rf writerLayer/
root@nicktming:/nicktming# ls
busybox busybox.tar mnt volume1 volume2
root@nicktming:/nicktming#
3. 实现
2.命令行实现中理解的, 其实只需要在原先的基础上加上
containerName
就可以了.
3.1 在创建mount的方法中增加containerName
func NewWorkDir(rootPath, containerName string, volumes []string) error {
if err := CreateContainerLayer(rootPath, containerName); err != nil {
return fmt.Errorf("CreateContainerLayer(%s) error: %v.\n", rootPath, err)
}
if err := CreateMntPoint(rootPath, containerName); err != nil {
return fmt.Errorf("CreateMntPoint(%s) error: %v.\n", rootPath, err)
}
if err := SetMountPoint(rootPath, containerName); err != nil {
return fmt.Errorf("SetMountPoint(%s) error: %v.\n", rootPath, err)
}
for _, volume := range volumes {
if err := CreateVolume(rootPath, volume, containerName); err != nil {
return fmt.Errorf("CreateVolume(%s, %s) error: %v.\n", rootPath, volume, err)
}
}
return nil
}
func CreateVolume(rootPath, volume, containerName string) error {
if volume != "" {
containerMntPath := rootPath + "/mnt/" + containerName
hostPath := strings.Split(volume, ":")[0]
exist, _ := PathExists(hostPath)
if !exist {
if err := os.MkdirAll(hostPath, 0777); err != nil {
log.Printf("mkdir %s err:%v\n", hostPath, err)
return fmt.Errorf("mkdir %s err:%v\n", hostPath, err)
}
}
mountPath := strings.Split(volume, ":")[1]
containerPath := containerMntPath + mountPath
if err := os.MkdirAll(containerPath, 0777); err != nil {
log.Printf("mkdir %s err:%v\n", containerPath, err)
return fmt.Errorf("mkdir %s err:%v\n", containerPath, err)
}
dirs := "dirs=" + hostPath
if _, err := exec.Command("mount", "-t", "aufs", "-o", dirs, "none", containerPath).CombinedOutput(); err != nil {
log.Printf("mount -t aufs -o %s none %s, err:%v\n", dirs, containerPath, err)
return fmt.Errorf("mount -t aufs -o %s none %s, err:%v\n", dirs, containerPath, err)
}
}
return nil
}
func CreateContainerLayer(rootPath, containerName string) error {
writerLayer := rootPath + "/writerLayer/" + containerName
if err := os.MkdirAll(writerLayer, 0777); err != nil {
log.Printf("mkdir %s err:%v\n", writerLayer, err)
return fmt.Errorf("mkdir %s err:%v\n", writerLayer, err)
}
return nil
}
func CreateMntPoint(rootPath, containerName string) error {
mnt := rootPath + "/mnt/" + containerName
if err := os.MkdirAll(mnt, 0777); err != nil {
log.Printf("mkdir %s err:%v\n", mnt, err)
return fmt.Errorf("mkdir %s err:%v\n", mnt, err)
}
return nil
}
func SetMountPoint(rootPath, containerName string) error {
dirs := "dirs=" + rootPath + "/writerLayer/" + containerName + ":" + rootPath + "/busybox"
mnt := rootPath + "/mnt/" + containerName
if _, err := exec.Command("mount", "-t", "aufs", "-o", dirs, "none", mnt).CombinedOutput(); err != nil {
log.Printf("mount -t aufs -o %s none %s, err:%v\n", dirs, mnt, err)
return fmt.Errorf("mount -t aufs -o %s none %s, err:%v\n", dirs, mnt, err)
}
return nil
}
3.2 在umount的方法中增加containerName
func ClearWorkDir(rootPath, containerName string, volumes []string) {
for _, volume := range volumes {
ClearVolume(rootPath, volume, containerName)
}
ClearMountPoint(rootPath, containerName)
ClearWriterLayer(rootPath, containerName)
}
func ClearVolume(rootPath, volume, containerName string) {
if volume != "" {
containerMntPath := rootPath + "/mnt/" + containerName
mountPath := strings.Split(volume, ":")[1]
containerPath := containerMntPath + mountPath
if _, err := exec.Command("umount", "-f", containerPath).CombinedOutput(); err != nil {
log.Printf("mount -f %s, err:%v\n", containerPath, err)
}
if err := os.RemoveAll(containerPath); err != nil {
log.Printf("remove %s, err:%v\n", containerPath, err)
}
}
}
func ClearMountPoint(rootPath, containerName string) {
mnt := rootPath + "/mnt/" + containerName
if _, err := exec.Command("umount", "-f", mnt).CombinedOutput(); err != nil {
log.Printf("mount -f %s, err:%v\n", mnt, err)
}
if err := os.RemoveAll(mnt); err != nil {
log.Printf("remove %s, err:%v\n", mnt, err)
}
}
func ClearWriterLayer(rootPath, containerName string) {
writerLayer := rootPath + "/writerLayer/" + containerName
if err := os.RemoveAll(writerLayer); err != nil {
log.Printf("remove %s, err:%v\n", writerLayer, err)
}
}
3.3 run方法修改
需要将
cmd.Dir
修改为当前容器的mount
位置/rootPath/mnt/containerName
func Run(command string, tty bool, cg *cgroups.CroupManger, rootPath string, volumes []string, containerName string) {
...
id := ContainerUUID()
if containerName == "" {
containerName = id
}
//log.Printf("volume:%s\n", volumes)
newRootPath := getRootPath(rootPath)
cmd.Dir = newRootPath + "/busybox"
if err := NewWorkDir(newRootPath, containerName, volumes); err == nil {
cmd.Dir = newRootPath + "/mnt/" + containerName
}
defer ClearWorkDir(newRootPath, containerName, volumes)
...
}
3.4 getRootPath方法
该方法主要解压
rootPath
下的busybox.tar
, 如果rootPath
用户没有指定,则使用默认值/nicktming
.
func getRootPath(rootPath string) string {
//log.Printf("rootPath:%s\n", rootPath)
defaultPath := DEFAULTPATH
if rootPath == "" {
log.Printf("rootPath is empaty, set rootPath: %s\n", defaultPath)
rootPath = defaultPath
}
imageTar := rootPath + "/busybox.tar"
exist, _ := PathExists(imageTar)
if !exist {
log.Printf("%s does not exist, set cmd.Dir by default: %s/mnt\n", imageTar, defaultPath)
return defaultPath
}
imagePath := rootPath + "/busybox"
if err := os.MkdirAll(imagePath, 0777); err != nil {
log.Printf("mkdir %s err:%v, set cmd.Dir by default: %s/mnt\n", imagePath, err, defaultPath)
return defaultPath
}
if _, err := exec.Command("tar", "-xvf", imageTar, "-C", imagePath).CombinedOutput(); err != nil {
log.Printf("tar -xvf %s -C %s, err:%v, set cmd.Dir by default: %s/mnt\n", imageTar, imagePath, err, defaultPath)
return defaultPath
}
return rootPath
}
3.5 测试
准备镜像
----------------------------------------------terminal 01--------------------------------------------------------
root@nicktming:/nicktming# ls
busybox.tar
启动第一个容器
container01
----------------------------------------------terminal 02--------------------------------------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container01 -v /nicktming/volume1:/containerVolume /bin/sh
2019/04/16 21:39:38 rootPath is empaty, set rootPath: /nicktming
2019/04/16 21:39:38 current path: /nicktming/mnt/container01.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 13:39 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 99 root root 0 Apr 16 13:39 proc
drwx------ 2 root root 4096 Apr 16 13:39 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # ls containerVolume/
/ # echo "cotainer01:test01" > containerVolume/test01.txt
/ # cat containerVolume/test01.txt
cotainer01:test01
/ #
查看宿主机内容
----------------------------------------------terminal 01--------------------------------------------------------
root@nicktming:/nicktming# ls
busybox busybox.tar mnt volume1 writerLayer
root@nicktming:/nicktming# ls volume1/
test01.txt
root@nicktming:/nicktming# cat volume1/test01.txt
cotainer01:test01
root@nicktming:/nicktming#
启动第二个容器
container02
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container02 -v /nicktming/volume2:/containerVolume /bin/sh
2019/04/16 21:57:58 rootPath is empaty, set rootPath: /nicktming
2019/04/16 21:57:58 current path: /nicktming/mnt/container02.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 13:57 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 99 root root 0 Apr 16 13:57 proc
drwx------ 2 root root 4096 Apr 16 13:58 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # ls -l containerVolume/
total 0
/ # echo "cotainer02:test01" > containerVolume/test01.txt
/ # ls -l containerVolume/
total 4
-rw-r--r-- 1 root root 18 Apr 16 13:58 test01.txt
/ # cat containerVolume/test01.txt
cotainer02:test01
/ #
再次查看宿主机
root@nicktming:/nicktming# ls
busybox busybox.tar mnt volume1 volume2 writerLayer
root@nicktming:/nicktming# ls -l volume2
total 4
-rw-r--r-- 1 root root 18 Apr 16 21:58 test01.txt
root@nicktming:/nicktming# cat volume2/test01.txt
cotainer02:test01
root@nicktming:/nicktming# cat volume1/test01.txt
cotainer01:test01
root@nicktming:/nicktming#
两个容器都退出
root@nicktming:/nicktming# cat volume1/test01.txt
cotainer01:test01
root@nicktming:/nicktming# cat volume2/test01.txt
cotainer02:test01
root@nicktming:/nicktming# ls -l busybox
total 48
drwxr-xr-x 2 root root 12288 Feb 15 02:58 bin
drwxr-xr-x 4 root root 4096 Mar 18 00:05 dev
drwxr-xr-x 3 root root 4096 Mar 18 00:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 15 02:58 home
drwxr-xr-x 2 root root 4096 Mar 18 00:05 proc
drwx------ 2 root root 4096 Feb 15 02:58 root
drwxr-xr-x 2 root root 4096 Mar 18 00:05 sys
drwxrwxrwt 2 root root 4096 Feb 15 02:58 tmp
drwxr-xr-x 3 root root 4096 Feb 15 02:58 usr
drwxr-xr-x 4 root root 4096 Feb 15 02:58 var
root@nicktming:/nicktming#
5. 实现根据镜像参数化
由于之前起的容器都是在代码里面写的
busybox
, 所以这里是将该部分参数化, 就是在命令行中指定使用什么镜像, 但是/rootPath
必须要有该镜像的压缩包(比如busybox.tar
).
5.1 增加获得imageName
var RunCommand = cli.Command{
Name: "run",
Flags: []cli.Flag {
...
},
Action: func(c *cli.Context) error {
...
imageName := c.Args().Get(0)
command := c.Args().Get(1)
...
Run(command, tty, &cg, rootPath, volumes, containerName, imageName)
return nil
},
}
修改
Run
方法
func Run(command string, tty bool, cg *cgroups.CroupManger, rootPath string, volumes []string, containerName, imageName string) {
...
id := ContainerUUID()
if containerName == "" {
containerName = id
}
//log.Printf("volume:%s\n", volumes)
// 修改处
newRootPath := getRootPath(rootPath, imageName)
//cmd.Dir = newRootPath + "/busybox"
if err := NewWorkDir(newRootPath, containerName, imageName, volumes); err == nil {
cmd.Dir = newRootPath + "/mnt/" + containerName
} else {
log.Printf("NewWorkDir error:%v\n", err)
return
}
defer ClearWorkDir(newRootPath, containerName, volumes)
...
}
在NewWorkDir方法加入了参数
imageName
, 因为SetMountPoint
方法中需要用到imageName
.
func SetMountPoint(rootPath, containerName, imageName string) error {
dirs := "dirs=" + rootPath + "/writerLayer/" + containerName + ":" + rootPath + "/" + imageName
mnt := rootPath + "/mnt/" + containerName
if _, err := exec.Command("mount", "-t", "aufs", "-o", dirs, "none", mnt).CombinedOutput(); err != nil {
log.Printf("mount -t aufs -o %s none %s, err:%v\n", dirs, mnt, err)
return fmt.Errorf("mount -t aufs -o %s none %s, err:%v\n", dirs, mnt, err)
}
return nil
}
另外
getRootPath
中也用到了busybox
, 做了以下改动:
func getRootPath(rootPath, imageName string) string {
//log.Printf("rootPath:%s\n", rootPath)
defaultPath := DEFAULTPATH
if rootPath == "" {
log.Printf("rootPath is empaty, set rootPath: %s\n", defaultPath)
rootPath = defaultPath
}
imageTar := rootPath + "/" + imageName + ".tar"
exist, _ := PathExists(imageTar)
if !exist {
log.Printf("%s does not exist, set cmd.Dir by default: %s/mnt\n", imageTar, defaultPath)
return defaultPath
}
imagePath := rootPath + "/" + imageName
if err := os.MkdirAll(imagePath, 0777); err != nil {
log.Printf("mkdir %s err:%v, set cmd.Dir by default: %s/mnt\n", imagePath, err, defaultPath)
return defaultPath
}
if _, err := exec.Command("tar", "-xvf", imageTar, "-C", imagePath).CombinedOutput(); err != nil {
log.Printf("tar -xvf %s -C %s, err:%v, set cmd.Dir by default: %s/mnt\n", imageTar, imagePath, err, defaultPath)
return defaultPath
}
return rootPath
}
5.2 测试
-----------------------------------------------terminal 01---------------------------------------------------------
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar
root@nicktming:/nicktming#
-----------------------------------------------terminal 02---------------------------------------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container01 -v /nicktming/volume1:/containerVolume busybox /bin/sh
2019/04/16 23:14:37 rootPath is empaty, set rootPath: /nicktming
2019/04/16 23:14:37 current path: /nicktming/mnt/container01.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 15:14 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 103 root root 0 Apr 16 15:14 proc
drwx------ 2 root root 4096 Apr 16 15:14 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # echo "container01:test01" > containerVolume/test01.txt
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
-----------------------------------------------terminal 03---------------------------------------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -it -name container02 -v /nicktming/volume2:/containerVolume busybox /bin/sh
2019/04/16 23:15:41 rootPath is empaty, set rootPath: /nicktming
2019/04/16 23:15:41 current path: /nicktming/mnt/container02.
/ # ls -l
total 48
drwxr-xr-x 2 root root 12288 Feb 14 18:58 bin
drwxr-xr-x 4 root root 4096 Apr 16 15:15 containerVolume
drwxr-xr-x 4 root root 4096 Mar 17 16:05 dev
drwxr-xr-x 3 root root 4096 Mar 17 16:05 etc
drwxr-xr-x 2 nobody nogroup 4096 Feb 14 18:58 home
dr-xr-xr-x 105 root root 0 Apr 16 15:15 proc
drwx------ 2 root root 4096 Apr 16 15:15 root
drwxr-xr-x 2 root root 4096 Mar 17 16:05 sys
drwxrwxrwt 2 root root 4096 Feb 14 18:58 tmp
drwxr-xr-x 3 root root 4096 Feb 14 18:58 usr
drwxr-xr-x 4 root root 4096 Feb 14 18:58 var
/ # echo "container02:test01" > containerVolume/test01.txt
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker#
-----------------------------------------------terminal 01---------------------------------------------------------
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# cat volume1/test01.txt
container01:test01
root@nicktming:/nicktming# cat volume2/test01.txt
container02:test01
root@nicktming:/nicktming#
6. 时序图
code-5.7.png
7. 参考
8. 全部内容
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]---网络实现测试
网友评论