美文网首页
[mydocker]---实现容器层隔离

[mydocker]---实现容器层隔离

作者: nicktming | 来源:发表于2019-05-12 08:40 被阅读0次

    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. 参考

    1. https://www.cnblogs.com/alantu2018/p/8465919.html

    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]---网络实现测试

    相关文章

      网友评论

          本文标题:[mydocker]---实现容器层隔离

          本文链接:https://www.haomeiwen.com/subject/zbqewqtx.html