概述
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)
}
}
最后
以上就是虚幻大碗为你收集整理的docker命令之images的全部内容,希望文章能够帮你解决docker命令之images所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复