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