美文网首页
[mydocker]---实现cp操作

[mydocker]---实现cp操作

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

1. 准备工作

本文会实现容器和宿主机之间文件的相互复制.

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.7.1
root@nicktming:~/go/src/github.com/nicktming/mydocker# git checkout -b dev-5.7.2

1.2 准备busybox.tar

// 前提条件
root@nicktming:/nicktming# pwd
/nicktming
root@nicktming:/nicktming# ls
busybox.tar

2. 方法

主要是测试一下copy, 很简单的操作. 在test/copy/test-1.go

func main()  {
    test01()
}

func test01()  {
    copy("/root/filecopy/busybox", "/root/filecopy/tmp")
    copy("/root/filecopy/busybox/bin/top", "/root/filecopy/tmp")
}

func copy(src, dst string) {
    exist, _ := command.PathExists(src)
    if !exist {
        log.Printf("src:%s not exists!\n", src)
        return
    }
    exist, _ = command.PathExists(dst)
    if !exist {
        log.Printf("dst:%s not exists!\n", src)
        return
    }
    if _, err := exec.Command("cp", "-r", src, dst).CombinedOutput(); err != nil {
        log.Printf("cp -r %s %s, err:%v\n", src, dst, err)
        return
    }
}

测试

root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# pwd
/root/go/src/github.com/nicktming/mydocker/test/copy
root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# ls -l /root/filecopy
total 8
drwxr-xr-x 12 root root 4096 Apr 19 06:53 busybox
drwxr-xr-x  2 root root 4096 Apr 19 06:55 tmp
root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# ls -l /root/filecopy/tmp/
total 0
root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# go run test-1.go 
root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# ls -l /root/filecopy/tmp/
total 1100
drwxr-xr-x 12 root root    4096 Apr 19 07:10 busybox
-rwxr-xr-x  1 root root 1120520 Apr 19 07:10 top
root@nicktming:~/go/src/github.com/nicktming/mydocker/test/copy# 

3.实现

在理解了Aufs的原理后, 实现这些操作基本上就是文件复制的问题, 只需要找到容器在宿主机上的挂载点就可以操作了, 如果是从容器内复制内容到宿主机, 则将找到要复制的文件在宿主机的某个位置即可, 然后该位置的文件复制到宿主机的另外一个位置即可. 反之也是一样.

那如何找到容器的挂载点呢?因为知道容器名, 所以可以直接从/var/run/mydocker中读该容器的metadata即可.

3.1 增加CopyCommand

// main.go
func main()  {
    ...
    app.Commands = []cli.Command{
        ...
        command.CopyCommand,
    }
    ...
}
// command/command.go
var CopyCommand = cli.Command{
    Name: "cp",
    Usage: "copy files",
    Action: func(c *cli.Context) error {
        source      := c.Args().Get(0)
        destination := c.Args().Get(1)
        log.Printf("source:%s, destination:%s\n", source, destination)
        Copy(source, destination)
        return nil
    },
}


3.2 增加command/copy.go

最终找到容器要操作的文件在宿主机的位置为containerMntPath, 而本身宿主机要操作的文件路径为hostPath.

func Copy(source, destination string)  {
    f1 := strings.Contains(source, ":")
    f2 := strings.Contains(destination, ":")
    if (f1 && f2) || (!f1 && !f2) {
        log.Printf("f1:%v, f2:%v, not correct format\n", f1, f2)
        return
    }

    var from_container_to_host bool = true
    containerUrl := source
    hostUrl      := destination
    if f2 {
        from_container_to_host = false
        containerUrl = destination
        hostUrl = source
    }
    containerName := strings.Split(containerUrl, ":")[0]
    containerPath := strings.Split(containerUrl, ":")[1]
    log.Printf("containerUrl:%s, hostUrl:%s, conatinerName:%s, containerPath:%s\n", containerUrl, hostUrl, containerName, containerPath)

    containerInfo, err := GetContainerInfo(containerName)
    if err != nil {
        log.Printf("GetContainerInfo error:%v\n", err)
        return
    }
    containerMntPath := containerInfo.RootPath + "/mnt/" + containerName + containerPath
    hostPath         := hostUrl
    log.Printf("containerPath:%s, hostPath:%s\n", containerMntPath, hostPath)

    log.Printf("from_container_to_host:%v\n", from_container_to_host)

    if from_container_to_host {
        log.Printf("from %s to %s\n", containerMntPath, hostPath)
        FileCopy(containerMntPath, hostPath)
    } else {
        log.Printf("from %s to %s\n", hostPath, containerMntPath)
        FileCopy(hostPath, containerMntPath)
    }
}

func FileCopy(src, dst string) {
    exist, _ := PathExists(src)
    if !exist {
        log.Printf("src:%s not exists!\n", src)
        return
    }
    exist, _ = PathExists(dst)
    if !exist {
        log.Printf("dst:%s not exists!\n", src)
        return
    }
    if _, err := exec.Command("cp", "-r", src, dst).CombinedOutput(); err != nil {
        log.Printf("cp -r %s %s, err:%v\n", src, dst, err)
        return
    }
}

3.2 测试

启动一个容器, 然后测试两个操作:
1. 容器往宿主机复制内容.
2. 宿主机往容器复制内容.

-------------------------------terminal 01----------------------------
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker run -d -name container01 busybox /bin/top
2019/04/19 15:19:56 rootPath is empaty, set rootPath: /nicktming
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker ps
ID                     NAME          PID         STATUS      COMMAND     CREATED
15556583962876437411   container01   18416       running     /bin/top    2019-04-19 15:19:56
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker exec container01 /bin/sh
2019/04/19 15:20:21 containerName:container01,command:/bin/sh
/ # ls -l
total 44
drwxr-xr-x    2 root     root         12288 Feb 14 18:58 bin
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 19 07:19 proc
drwx------    2 root     root          4096 Apr 19 07:20 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

-------------------------------terminal 02----------------------------
root@nicktming:/nicktming# mkdir copy && echo "copy files" > copy/test01.txt
// 从宿主机copy文件到容器中
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker cp /nicktming/copy/test01.txt container01:/
2019/04/19 15:49:50 source:/nicktming/copy/test01.txt, destination:container01:/
2019/04/19 15:49:50 containerUrl:container01:/, hostUrl:/nicktming/copy/test01.txt, conatinerName:container01, containerPath:/
2019/04/19 15:49:50 containerPath:/nicktming/mnt/container01/, hostPath:/nicktming/copy/test01.txt
2019/04/19 15:49:50 from_container_to_host:false
2019/04/19 15:49:50 from /nicktming/copy/test01.txt to /nicktming/mnt/container01/
root@nicktming:~/go/src/github.com/nicktming/mydocker#
 
// 从容器中copy文件到宿主机
root@nicktming:~/go/src/github.com/nicktming/mydocker# ./mydocker cp container01:/bin/top /root/go/src/github.com/nicktming/mydocker
2019/04/19 15:51:00 source:container01:/bin/top, destination:/root/go/src/github.com/nicktming/mydocker
2019/04/19 15:51:00 containerUrl:container01:/bin/top, hostUrl:/root/go/src/github.com/nicktming/mydocker, conatinerName:container01, containerPath:/bin/top
2019/04/19 15:51:00 containerPath:/nicktming/mnt/container01/bin/top, hostPath:/root/go/src/github.com/nicktming/mydocker
2019/04/19 15:51:00 from_container_to_host:true
2019/04/19 15:51:00 from /nicktming/mnt/container01/bin/top to /root/go/src/github.com/nicktming/mydocker
// 验证top命令是否copy到当前位置
root@nicktming:~/go/src/github.com/nicktming/mydocker# ls
cgroups  command  main.go  memory  mydocker  nsenter  pictures  README.md  test  top  urfave-cli-examples
root@nicktming:~/go/src/github.com/nicktming/mydocker# 

// 查看容器中是否有test1.txt文件
-------------------------------terminal 01----------------------------
/ # ls -l
total 48
drwxr-xr-x    2 root     root         12288 Feb 14 18:58 bin
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  102 root     root             0 Apr 19 07:19 proc
drwx------    2 root     root          4096 Apr 19 07:20 root
drwxr-xr-x    2 root     root          4096 Mar 17 16:05 sys
-rw-r--r--    1 root     root            11 Apr 19 07:49 test01.txt
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
/ # cat test01.txt 
copy files
/ # exit
root@nicktming:~/go/src/github.com/nicktming/mydocker# 
  1. 时序图
copy.png

5. 参考

1. 自己动手写docker.(基本参考此书,加入一些自己的理解,加深对docker的理解)

6. 全部内容

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]---实现cp操作

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