简介
在上篇中,我们实现了 volume,让容器能挂载宿主机文件,实现持久化。本篇中将实现 commit 命令,将运行中的容器进行保存
源码说明
同时放到了 Gitee 和 Github 上,都可进行获取
本章节对应的版本标签是:4.4,防止后面代码过多,不好查看,可切换到标签版本进行查看
代码实现
上篇中,我们实现了-v 命令,通过挂载宿主机上的文件,类似文件共享,实现了容器的文件持久化
但我们的容器在退出后,已经会把可写层的内容删除掉
在我们使用 docker 的过程,我们会使用 commit 命令,将正在运行中的容器进行保存,成一个新的镜像,当启动这个镜像时,我们在可写层的东西依旧存在
本篇中我们就要实现这个功能的基础,当然没有像 docker 那样,能直接 commit 成一个新的镜像
本篇中如书中所说,简单的镜像打包
其中核心的就是将我们的挂载点镜像打包即可,因为挂载点中,挂载着 busybox 基础只读层、可写层、宿主机的挂载数据卷,即存放着我们当前的所有数据
所以我们直接将其进行打包即可
核心的代码就是:
1.新增 commit 命令:后面的参数是打包的镜像名称
main 函数中新增 commit 命令:
func main() { ......
app.Commands = []cli.Command{ command.InitCommand, command.RunCommand, command.CommitCommand, }
......}
复制代码
Commit 命令的新增,在 main_command.go 文件中
var CommitCommand = cli.Command{ Name: "commit", Usage: "commit a container into image", Action: func(context *cli.Context) error { if len(context.Args()) < 1 { return fmt.Errorf("Missing container name") } imageName := context.Args().Get(0) return run.CommitContainer(imageName) },}
复制代码
2.commit 的具体实现:将挂载点进行打包
和书中不同,它是固定的 root 目录作为容器固定挂载父目录
这里我意识到,自己去取当前命令运行的目前是不恰当,可以将/root 看出我们 docker 的安装目录,相关的存储都放到/root 下
这里是我考虑不当了,所以导致我们的 commit 运行都必须在工程目录下,这样才能正确打包
但问题不大,就当暂时设置的存储目录是工程源码跟路径了
或许后期可以把这个路径抽出来,做成可以配置的
func CommitContainer(imageName string) error { pwd, err := os.Getwd() if err != nil { return fmt.Errorf("Run get pwd err: %v", err) } mntUrl := pwd + "/mnt/" imageTar := pwd + "/" + imageName + ".tar" log.Infof("commit file path: %s", imageTar) if _, err := exec.Command("tar", "-czf", imageTar, "-C", mntUrl, ".").CombinedOutput(); err != nil { return fmt.Errorf("tar folder err: %s, %v", mntUrl, err) } log.Infof("end commit file: %s", imageTar) return nil}
复制代码
运行测试
首先我们启动一个容器
➜ dockerDemo git:(main) ✗ ./main run -ti sh{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"memory cgroup path: /sys/fs/cgroup/memory/mydocker-cgroup","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"all command is : sh","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"parent process run","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"init come on","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"current location: /home/lw/code/go/dockerDemo/mnt","time":"2022-03-20T14:08:36+08:00"}{"level":"info","msg":"find path: /bin/sh","time":"2022-03-20T14:08:36+08:00"}/ #
复制代码
然后新开一个 shell,运行 commit 命令
➜ dockerDemo git:(main) ✗ ./main commit image{"level":"info","msg":"commit file path: /home/lw/code/go/dockerDemo/image.tar","time":"2022-03-20T14:13:00+08:00"}
➜ dockerDemo git:(main) ✗➜ dockerDemo git:(main) ✗ lsbusybox docs example go.mod go.sum image.tar LICENSE main mnt mydocker mydocker.tar README.md untar writeLayer➜ dockerDemo git:(main) ✗ mkdir ./untar➜ dockerDemo git:(main) ✗ cd untar➜ untar git:(main) ✗ tar -xvf ../image.tar
➜ untar git:(main) ✗ lsbin dev etc home main proc root sys tmp usr var➜ untar git:(main) ✗
复制代码
如上面所示,我们将我们正在运行中的达成 image.tar,然后解压查看里面的内容,和我们的运行容器时的跟目录一样
注:打包花的时间有一定的时间,需要耐心等 20 秒左右
评论