简介
在上篇中,我们实现了 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) ✗ ls
busybox 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) ✗ ls
bin dev etc home main proc root sys tmp usr var
➜ untar git:(main) ✗
复制代码
如上面所示,我们将我们正在运行中的达成 image.tar,然后解压查看里面的内容,和我们的运行容器时的跟目录一样
注:打包花的时间有一定的时间,需要耐心等 20 秒左右
评论