docker命令之images

docker命令之images

1 命令流程:

CmdImages(命令行) -------> getImagesJSON (httpserver handler)----->  Images(job)


2、CmdImages分析

位置api/client/command.go的CmdImages 

解析命令行,提取options(-a、-q、-t、-v、--no-trunc),在从httpserver返回的数据中根据不同的filter输出对应的东东

quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
	all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (by default filter out the intermediate image layers)")
	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
	// FIXME: --viz and --tree are deprecated. Remove them in a future version.
	flViz := cmd.Bool([]string{"#v", "#viz", "#-viz"}, false, "Output graph in graphviz format")
	flTree := cmd.Bool([]string{"#t", "#tree", "#-tree"}, false, "Output graph in tree format")

	flFilter := opts.NewListOpts(nil)
	cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')")
向httpserver发起请求,将数据放在body中

body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, false))
		if err != nil {
			return err
		}

创建存储httpserver返回的body的表outs,size为0,将body中的数据放入表outs中,此表中存储repository中各层的信息???

再创建一个roots表,此表用于根image

		outs := engine.NewTable("Created", 0)
		if _, err := outs.ReadListFrom(body); err != nil {
			return err
		}

		var (
			printNode  func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)
			startImage *engine.Env

			roots    = engine.NewTable("Created", outs.Len())
			byParent = make(map[string]*engine.Table)
		)
如果打开了--tree或-v选项,解析表中的数据。如果没有ParentId,那么此层就是最原始的一层。加入到roots的最底层;如果parentId不是空,就说明此层是孩子层,根据此层的ParentId找到它的父层。
for _, image := range outs.Data {
			if image.Get("ParentId") == "" {
				roots.Add(image)
			} else {
				if children, exists := byParent[image.Get("ParentId")]; exists {
					children.Add(image)
				} else {
					byParent[image.Get("ParentId")] = engine.NewTable("Created", 1)
					byParent[image.Get("ParentId")].Add(image)
				}
			}

			if matchName != "" {
				if matchName == image.Get("Id") || matchName == utils.TruncateID(image.Get("Id")) {
					startImage = image
				}

				for _, repotag := range image.GetList("RepoTags") {
					if repotag == matchName {
						startImage = image
					}
				}
			}
		}

--tree参数的输出



-v参数的输出


2 httpserver介绍到client端的请求,由getImagesJSON处理

解析client请求

if err := parseForm(r); err != nil {
		return err
	}
初始化job变量,err介绍job报错,outs存储job输出的镜像数据,job:执行任务的job实体

var (
		err  error
		outs *engine.Table
		job  = eng.Job("images")
	)

初始化job的filters

job.Setenv("filters", r.Form.Get("filters"))
	// FIXME this parameter could just be a match filter
	job.Setenv("filter", r.Form.Get("filter"))
	job.Setenv("all", r.Form.Get("all"))
解析job任务完成而得到的outs数据,并格式化,将要返回client的数据放入w相应数据包中

if version.LessThan("1.7") && outs != nil { // Convert to legacy format
		outsLegacy := engine.NewTable("Created", 0)
		for _, out := range outs.Data {
			for _, repoTag := range out.GetList("RepoTags") {
				parts := strings.Split(repoTag, ":")
				outLegacy := &engine.Env{}
				outLegacy.Set("Repository", parts[0])
				outLegacy.Set("Tag", parts[1])
				outLegacy.Set("Id", out.Get("Id"))
				outLegacy.SetInt64("Created", out.GetInt64("Created"))
				outLegacy.SetInt64("Size", out.GetInt64("Size"))
				outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize"))
				outsLegacy.Add(outLegacy)
			}
		}
		w.Header().Set("Content-Type", "application/json")
		if _, err := outsLegacy.WriteListTo(w); err != nil {
			return err
		}
	}


3 CmdImages(server/server.go)

一个repository包含了许多的layer,每个layer叫做一个image,image使用结构体Image描述

ID:此层的id

Parent:此层的父层

Comment:此层的描述

Create:创建时间

Container:使用此层的Container id

ContainerConfig:Container配置信息

DockerVersion:当前docker版本

Author:所有人

Config:这个也是Container的配置,但还没搞明白它与ContainerConfig之间的关系,待后续分析

Architecture:架构

OS:操作系统类型

Size:层大小

type Image struct {
	ID              string            `json:"id"`
	Parent          string            `json:"parent,omitempty"`
	Comment         string            `json:"comment,omitempty"`
	Created         time.Time         `json:"created"`
	Container       string            `json:"container,omitempty"`
	ContainerConfig runconfig.Config  `json:"container_config,omitempty"`
	DockerVersion   string            `json:"docker_version,omitempty"`
	Author          string            `json:"author,omitempty"`
	Config          *runconfig.Config `json:"config,omitempty"`
	Architecture    string            `json:"architecture,omitempty"`
	OS              string            `json:"os,omitempty"`
	Size            int64

	graph Graph
}

在server.go中Images方法处理从httpserver过来的请求

首先解析filters,这个字段的含义是得到命令行中要过滤出那个repo,例如 docker images xxxx,那么xxxx就是filters,命令的输出就是关于xxxx镜像的内容。

另外imageFilters中如果携带了dangling字段,并且为true的话,那么就置filt_tagged为false,这个参数的含义是如果为true的话,过滤到中间层,只取有repo name的镜像,

即只取打了tag的镜像。

imageFilters, err := filters.FromParam(job.Getenv("filters"))
	if err != nil {
		return job.Error(err)
	}
	if i, ok := imageFilters["dangling"]; ok {
		for _, value := range i {
			if strings.ToLower(value) == "true" {
				filt_tagged = false
			}
		}
	}

if job.GetenvBool("all") && filt_tagged {
		allImages, err = s.graph.Map()
	} else {
		allImages, err = s.graph.Heads()
	}

get所有镜像,不管是否打了tag

if job.GetenvBool("all") && filt_tagged {
		allImages, err = srv.daemon.Graph().Map()
	} else {
		allImages, err = srv.daemon.Graph().Heads()
	}
lookup存储找到的repository

lookup := make(map[string]*engine.Env)

对所有的images安装条件过滤。如果在命令行中指定了repository,例如docker images xxxx,那么只找job.Getenv("filter")的镜像信息。

如果没有,找到所有打了tag的repository。第一for是轮训所有的repository,第二个for是将带有tag的镜像记录在lookup中。

并将带有tag的镜像从allImages中删除。

	for name, repository := range srv.daemon.Repositories().Repositories {
		if job.Getenv("filter") != "" {
			if match, _ := path.Match(job.Getenv("filter"), name); !match {
				continue
			}
		}
		for tag, id := range repository {
			image, err := srv.daemon.Graph().Get(id)
			if err != nil {
				log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err)
				continue
			}

			if out, exists := lookup[id]; exists {
				if filt_tagged {
					out.SetList("RepoTags", append(out.GetList("RepoTags"), fmt.Sprintf("%s:%s", name, tag)))
				}
			} else {
				// get the boolean list for if only the untagged images are requested
				delete(allImages, id)
				if filt_tagged {
					out := &engine.Env{}
					out.Set("ParentId", image.Parent)
					out.SetList("RepoTags", []string{fmt.Sprintf("%s:%s", name, tag)})
					out.Set("Id", image.ID)
					out.SetInt64("Created", image.Created.Unix())
					out.SetInt64("Size", image.Size)
					out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
					lookup[id] = out
				}
			}

		}
	}
创建返回给httpserver的存储image信息的outs表,并将查找到的lookup装入表中

outs := engine.NewTable("Created", len(lookup))
	for _, value := range lookup {
		outs.Add(value)
	}

如果在命令行中没有指定要查找的镜像名。那么将allImages中剩下的所有没有打tag的镜像也放回给httpserver,

在RepoTags字段填充none

if job.Getenv("filter") == "" {
		for _, image := range allImages {
			out := &engine.Env{}
			out.Set("ParentId", image.Parent)
			out.SetList("RepoTags", []string{"<none>:<none>"})
			out.Set("Id", image.ID)
			out.SetInt64("Created", image.Created.Unix())
			out.SetInt64("Size", image.Size)
			out.SetInt64("VirtualSize", image.GetParentsSize(0)+image.Size)
			outs.Add(out)
		}
	}





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值