[docker 1.13 源码分析]第三章 docker pull image

来源:互联网 发布:unity3d和虚幻4区别 编辑:程序博客网 时间:2024/05/18 09:05


1.0 Image主要命令


  • $ docker images (所有)
  • $ docker images java (所有java
  • $ docker images java:8 (固定tagjave
  • $ docker images --no-trunc (所有id值全长度)
  • $ docker images --digests (所有镜像带有digest
  • $ docker images --format "{{.ID}}: {{.Repository}}" (列出两项)
  • $ docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" (列出三项)

pull主要命令

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]Pull an image or a repository from a registryOptions:  -a, --all-tags                Download all tagged images in the repository      --disable-content-trust   Skip image verification (default true)      --help                    Print usage




1.1 镜像的子命令

 

 

1.2 Named接口

 

 


拉取镜像的命令: docker pull NAME[:TAG|@DIGEST] ,TAG标签,DIGEST数字摘要,就是拉取镜像可以附带TAG或数字摘要等参数,或只使用镜像名(默认latest)。如果参数带TAG则使用NamedTagged描述 ,如果参数带DIGEST则使用Canonical 描述。

  • $ docker images --digests
  • $ docker mysql@sha256:89cc6ff6a7ac9916c3384e864fb04b8ee9415b572f872a2a4cf5b909dbbca81b
  • $ docker pull library/mysql


1.3 runPull函数

下面分析NewPullCommand这个子命令,位于cli/image/pull.go文件中。主要执行函数是runPull

 

 

① reference.ParseNamed: 从参数中解析镜像仓库地址等信息,如参数中没有仓库信息,则使用默认的docker.io

② opts.all && !reference.IsNameOnly(distributionRef): 如果使用了-a / --all-tags,但又含有tag信息则报错,如下

$ docker pull -a ubuntu:latest

   tag can't be used with --all-tags/-a

③ !opts.all && reference.IsNameOnly(distributionRef): 如果无-a / --all-tags参数,而只有镜像名,则使用默认latesttag

④ ImagePullPrivileged: 拉取镜像发送请求至dockerd,使用ImagePull(1.6中讲解)


1.4 Parse函数

 

ReferenceRegexp定义在vendor/github.com/docker/distribution/reference/regexp.go


 

1.5 getBestReferenceType函数

① 带镜像名,则matches[1]不为nil;

② 带tag,则matches[2]不为nil;

③ 带数字摘要,则matches[3]不为nil

getBestReferenceType根据各个matchs是否为空,根据带相应的部分返回不同类型的Reference接口。

 

 

1.6 ImagePull函数

文件位置client/image_pull.go tryImageCreate调用http请求/images/create,

根据api路由定位到daemon/image_pull.go文件中的PullImage函数,下面讲解该函数。

 


1.7 PullImage函数

 

主要函数是daemon.pullImageWIthReferenceclient端验证这边也验证一遍,不知道是否多余,可能更安全一些吧!继续分析


1.8  pullImageWithReference函数

ImagePullConfig文件位于distribution/pull.go填充一些配置信息,包括一些接口方法,结构体如下所示:

 

主要函数是distribution.Pull, 初始化pull操作,镜像是repository名字,tag可以为空或者指定的。

 

 

1.9 Pull函数

概念: index用来管理用户账号,权限,搜索,打标签(tagging),以及其它可以方便的通过Web界面来完成的工作。

registry则是真正的用来保存、提供镜像文件的概念。它通过索引(index)来完成用户认证步骤。

当执行docker search命令时,Docker会到index里查找,而不是registry。实际上Docker会在index所知道的多个registry中进行查找。


文件位于distribution/pull.go中,

 

拆分reference.Named,配置成RepositoryInfo(描述repository)结构体如下所示,

 

 

 

返回APIEndpoint列表pull的endpoints


for _, endpoint := range endpoints {if confirmedV2 && endpoint.Version == registry.APIVersion1 {logrus.Debugf("Skipping v1 endpoint %s because v2 registry was detected", endpoint.URL)continue}if endpoint.URL.Scheme != "https" {if _, confirmedTLS := confirmedTLSRegistries[endpoint.URL.Host]; confirmedTLS {logrus.Debugf("Skipping non-TLS endpoint %s for host/port that appears to use TLS", endpoint.URL)continue}}logrus.Debugf("Trying to pull %s from %s %s", repoInfo.Name(), endpoint.URL, endpoint.Version)puller, err := newPuller(endpoint, repoInfo, imagePullConfig)if err != nil {lastErr = errcontinue}if err := puller.Pull(ctx, ref); err != nil {// Was this pull cancelled? If so, don't try to fall// back.fallback := falseselect {case <-ctx.Done():default:if fallbackErr, ok := err.(fallbackError); ok {fallback = trueconfirmedV2 = confirmedV2 || fallbackErr.confirmedV2if fallbackErr.transportOK && endpoint.URL.Scheme == "https" {confirmedTLSRegistries[endpoint.URL.Host] = struct{}{}}err = fallbackErr.err}}if fallback {if _, ok := err.(ErrNoSupport); !ok {// Because we found an error that's not ErrNoSupport, discard all subsequent ErrNoSupport errors.discardNoSupportErrors = true// append subsequent errorslastErr = err} else if !discardNoSupportErrors {// Save the ErrNoSupport error, because it's either the first error or all encountered errors// were also ErrNoSupport errors.// append subsequent errorslastErr = err}logrus.Errorf("Attempting next endpoint for pull after error: %v", err)continue}logrus.Errorf("Not continuing with pull after error: %v", err)return translatePullError(err, ref)}imagePullConfig.ImageEventLogger(ref.String(), repoInfo.Name(), "pull")return nil}

这段代码看似挺多,主要做了就是找到endpoints, 然后puller.Pull工作,出错了进行错误整理。

看看v2Puller结构体如下所示:


V2Puller结构体方法Pull方法下面进行讲解


1.10 Pull函数

位于文件distribution/pull_v2.go文件。


调用NewV2Repository函数来创建一个提供身份验证的http传输通道,并返回repository接口,如下所示:客户端的client中的registry实现了该接口,文件位于vendor/github.com/docker/distribution/registry/client/repository.go



pullV2Repository函数主要方法是p.pullV2Tag函数,如果不是只有单独名字(比如只有ubuntu)直接使用pullV2Tag方法。



1.11 pullV2Tag函数

位于文件distribution/pull_v2.go文件中。前面都是配置以及验证工作,pullV2Tag才是真正的最后的下载环节,涉及的内容比较多。

 

获取首选项的mainfest服务

 

 

这一段就是根据tag或者数字摘要进行manSvc.Get方法,以指定的degest检索,并返回distribution.Mainfest接口。














 


0 0
原创粉丝点击