美文网首页
[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