docker命令之commit

1、命令用法

docker commit -a|--author[=""] -m|--message[=""] CONTAINER [REPOSITORY[:TAG]]

docker version:1.0.0

2、命令分析

例如 docker commit -a=author -m=balabala container-name repo:t

CmdCommit(api/client/command.go)----> PostCommit(api/server/server.go) ---> ContainerCommit(server/server.go)

3 步骤

3.1 CmdCommit

解析命令行参数。

name:Container名

repository:registry名

tag:tag名

if cmd.NArg() == 3 {
		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'CONTAINER [REPOSITORY [TAG]]' as been deprecated. Please use CONTAINER [REPOSITORY[:TAG]]\n")
		name, repository, tag = cmd.Arg(0), cmd.Arg(1), cmd.Arg(2)
	} else {
		name = cmd.Arg(0)
		repository, tag = utils.ParseRepositoryTag(cmd.Arg(1))
	}
解析registry是否正确
if repository != "" {
		if _, _, err := registry.ResolveRepositoryName(repository); err != nil {
			return err
		}
	}

请求包变量填充,其中config是名为name的Container配置

v := url.Values{}
	v.Set("container", name)
	v.Set("repo", repository)
	v.Set("tag", tag)
	v.Set("comment", *flComment)
	v.Set("author", *flAuthor)
	var (
		config *runconfig.Config
		env    engine.Env
	)

向httpserver发起请求并解析返回的结果

stream, _, err := cli.call("POST", "/commit?"+v.Encode(), config, false)
	if err != nil {
		return err
	}
	if err := env.Decode(stream); err != nil {
		return err
	}
3.2 PostCommit

设置job环境参数

job.Setenv("repo", r.Form.Get("repo"))
job.Setenv("tag", r.Form.Get("tag"))
job.Setenv("author", r.Form.Get("author"))
job.Setenv("comment", r.Form.Get("comment"))
job.SetenvSubEnv("config", &config)

运行job并返回生成的镜像id

if err := job.Run(); err != nil {
		return err
	}
	env.Set("Id", engine.Tail(stdoutBuffer, 1))

3.3 ContainerCommit

得到镜像名并 通过镜像名得到container

name := job.Args[0]

	container := srv.daemon.Get(name)
	if container == nil {
		return job.Errorf("No such container: %s", name)
	}
获取Container配置,并新建一个配置变量
var (
		config    = container.Config
		newConfig runconfig.Config
	)
将命令上中携带的配置放入newConfig中
if err := job.GetenvJson("config", &newConfig); err != nil {
		return job.Error(err)
	}
将镜像中的Container配置合入新的配置中
if err := runconfig.Merge(&newConfig, config); err != nil {
		return job.Error(err)
	}
做提交操作,job环境变量中的repo、tag将在将来要生成的lay作为标记
img, err := srv.daemon.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig)
	if err != nil {
		return job.Error(err)
	}

3.4 srv .daemon.Commit----> Commit(daemon/daemon.go)
挂在Container的文件系统,Mount操作实际是就是将
if err := container.Mount(); err != nil {
		return nil, err
	}
对当前layer打包,ExportRw方法使用daemon的diff方法找出文件系统中变化的部分并打包
rwTar, err := container.ExportRw()
	if err != nil {
		return nil, err
	}
创建新的layer
var (
		containerID, containerImage string
		containerConfig             *runconfig.Config
	)

	if container != nil {
		containerID = container.ID
		containerImage = container.Image
		containerConfig = container.Config
	}

	img, err := daemon.graph.Create(rwTar, containerID, containerImage, comment, author, containerConfig, config)
	if err != nil {
		return nil, err
	}
如果有tag信息,将tag打到新layer上
if repository != "" {
		if err := daemon.repositories.Set(repository, tag, img.ID, true); err != nil {
			return img, err
		}
	}

在向下分析就是文件系统驱动了,比如如何给Container中变动的东东做diff之类的,这部分还需要时间深入的了解docker使用各种文件系统驱动及文件系统本身。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值