文章目录
- 目标
- 注意
- exec.Command
- tar
- 代码
- 结果
目标
piveroot切换工作目录到/merged后,通过docker commit将此时工作目录的文件系统保存下来,使用tar包将该文件系统打包为tar文件
命令类似 ./mydocker commit myimage
然后当前目录下会得到myimage.tar
注意
- 执行commit操作是在另一个终端执行的,也就是说容器已启动并运行,此时在另一个终端执行commit操作的时候不需要在挂载或启动子进程等操作,直接是设置一个位置来存,而不是像之前一样联合挂载后再得到具体的工作目录地址了
exec.Command
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
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)
}
}
判断参数个数,并最后做出相应执行
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文件
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