[mydocker]---實現容器層隔離

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]---網絡實現測試

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,237評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,957評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,248評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,356評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,081評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,485評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,534評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,720評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,263評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,025評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,204評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,787評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,461評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,874評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,105評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,945評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,205評論 2 375

推薦閱讀更多精彩內容