从零自制docker-14-【实现 mydocker commit 打包容器成镜像】

文章目录

目标

piveroot切换工作目录到/merged后,通过docker commit将此时工作目录的文件系统保存下来,使用tar包将该文件系统打包为tar文件

命令类似 ./mydocker commit myimage然后当前目录下会得到myimage.tar

注意

  • 执行commit操作是在另一个终端执行的,也就是说容器已启动并运行,此时在另一个终端执行commit操作的时候不需要在挂载或启动子进程等操作,直接是设置一个位置来存,而不是像之前一样联合挂载后再得到具体的工作目录地址了

exec.Command

python 复制代码
exec.Command("tar", "-czf", imageTar, "-C", mntPath, ".").CombinedOutput()

这段代码是使用Go语言的标准库os/exec来执行一个外部命令,具体是调用tar命令来创建一个压缩的归档文件。这里是逐部分解释:

  • exec.Command: 这是Go语言中用于创建并运行外部命令的对象。它接受一个可变数量的字符串参数,第一个参数是命令名,后面的参数是传递给该命令的各个选项和参数。

  • "tar": 这是命令本身,tar是一个用于创建、读取、更新和管理归档文件的工具。

  • "-czf": 这些是传递给tar命令的选项。

    • -c 表示创建一个新的归档文件。这意味着你要使用 tar 命令来打包当前目录下一系列文件和目录成为一个单一的归档文件(通常是以 .tar 结尾)。这个过程不会对文件进行压缩,只是简单地将它们收集在一起形成一个归档文件,便于管理和传输。
    • -z 表示在创建归档文件时进行gzip压缩。结合 -c,这会创建一个.tar.gz格式的压缩归档文件。
    • -f 后面跟归档文件的名称。注意,由于-f需要直接跟着文件名,所以在参数列表中,imageTar变量将会作为此选项的值。
  • imageTar: 这是一个变量,代表要创建的归档文件的名称(包括路径)。例如,如果imageTar的值为/path/to/image.tar.gz,那么这个归档文件就会被创建在指定路径,并命名为image.tar.gz

  • "-C": 这个选项告诉tar在执行操作前先切换到指定的目录。这里的指定目录由接下来的参数决定。

  • mntPath: 这也是一个变量,代表一个目录路径。结合-C选项,它指定了tar执行操作前应先切换到的目录。例如,如果mntPath的值为/mnt/mydir,则会在执行打包操作前进入该目录。

  • ".": 这是一个点字符,代表当前目录。在tar命令的上下文中,它意味着打包当前目录下的所有内容。由于之前使用了-C指定了目录,这里的"当前目录"就是mntPath所指的目录。

  • .CombinedOutput(): 这个方法用来执行上述构造的命令,并捕获其标准输出和标准错误的组合输出。返回的是一个字节切片,包含命令执行后的输出文本。这在调试或需要处理命令输出的场景中非常有用。

综上所述,这段代码的功能是:在Go程序中执行一个命令,使用tar工具将mntPath目录下的所有内容打包成一个gzip压缩的归档文件,并保存为imageTar变量指定的路径和文件名。

tar

  • tar: 是 tape archive 的缩写,是一个用于创建、提取和查看 tarball(.tar 文件)的工具。
  • -t 选项:表示列出(list)tar 文件内的内容。当你对一个 .tar 文件使用 -t 选项时,tar 命令将会输出该归档文件中所有文件和目录的列表,但并不解压或提取它们。
  • -f 选项:后面跟需要操作的 tar 文件名。-f 是 file 的缩写,用来指定要处理的归档文件。

所以,当你运行 tar -tf somefile.tar 命令时,它会列出 somefile.tar 这个归档文件内部的所有文件和目录结构,每一项占一行,但并不会展开或提取这个归档文件的实际内容。这对于快速检查一个 tar 文件包含哪些内容而不需要真正提取它非常有用。

代码

https://github.com/FULLK/llkdocker/tree/main/commit_docker

增加一个command

go 复制代码
func main(){
	//定义相关命令
	app:=cli.NewApp()
	app.Name="llkdocker"
	app.Usage="my simple docker -llkdocker "
	app.Commands=[]cli.Command{
		runcommand,
		initcommand,
		commitcommand,
	}//Commands 属性是一个 []cli.Command 类型的切片

	app.Before=func(context *cli.Context)error{

	log.SetFormatter(&log.JSONFormatter{})
	log.SetOutput(os.Stdout)
	return nil
	} //在处理命令参数之前先进行的函数

	if err:=app.Run(os.Args);err!=nil{
		log.Fatal(err)
	}
}

判断参数个数,并最后做出相应执行

go 复制代码
var commitcommand = cli.Command{
	Name:  "commit",
	Usage: "commit  image",
	Action: func(context *cli.Context)error {
		args := context.Args()//commit后参数的作为这里
		if len(args)<1 {
			log.Fatal("missing the image name you want to save ")
		}

		log.Info(args)
		contain.Contain_commit(args)
		return nil
	},
}

这里注意tar打包好像最后只能生成一个tar文件

go 复制代码
func Contain_commit(imagename []string){
	mnturl:="/home/llk/Desktop/llkdocker/commit_docker/merged"
	rooturl:="/home/llk/Desktop/llkdocker/commit_docker"
	/*
	var params string
	for i := 0; i < len(imagename); i++ {
	param := rooturl+"/"+imagename[i]+".tar "
	params =params+param   
	}	 //得到参数
	log.Info(params) //类似 路径/1.tar 路径/2.tar 但一次只能生成一个镜像
	*/
	imagetar:=rooturl+"/"+imagename[0]+".tar"
	log.Info(imagetar)

	if len(imagename)>1{
		log.Infof("too many image name ,we only can tar the first")

	}
	if _,err:=exec.Command("tar","-czf",imagetar,"-C",mnturl,".").CombinedOutput();err!=nil{
		log.Info(err)
		log.Fatal("tar error !!!")  //好像一次只能生成一个tar包 
	}
	log.Info("commit finish") //tar需要一定时间,这里做最后结束的回现

}

结果

先在一个终端启动

然后再启动另一个终端commit

相关推荐
大熊程序猿2 小时前
K8s证书过期
云原生·容器·kubernetes
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel
公贵买其鹿4 小时前
List深拷贝后,数据还是被串改
java
摸鱼也很难5 小时前
Docker 镜像加速和配置的分享 && 云服务器搭建beef-xss
运维·docker·容器
xlsw_7 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹7 小时前
基于java的改良版超级玛丽小游戏
java
鸠摩智首席音效师7 小时前
Docker 中如何限制CPU和内存的使用 ?
docker·容器
Michaelwubo8 小时前
Docker dockerfile镜像编码 centos7
运维·docker·容器
jingyu飞鸟8 小时前
centos-stream9系统安装docker
linux·docker·centos
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭8 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员