Docker镜像名称如何解析?

在做docker push镜像或拉镜像时,Docker如何确定镜像名称中是否存在注册表服务器,或者默认注册表中它是否为路径/用户名(例如Docker

Hub)?

我从1.1图像规范中看到以下内容:

标签用于将用户提供的描述性名称映射到任何单个图像ID。标记值限于字符集[a-zA-Z_0-9]。

标签的集合,这些标签被分组在一个共同的前缀下:(:之前的名称部分)。例如,在标记有名称my-app:3.1.4的图像中,my-

app是名称的存储库组件。存储库名称由斜杠分隔的名称组成,可以选择以DNS主机名作为前缀。主机名必须遵循标准的DNS规则,但不得包含_字符。如果存在主机名,则可以选择后跟端口号:8080。名称组件可能包含小写字符,数字和分隔符。分隔符定义为一个句点,一个或两个下划线或一个或多个破折号。名称组件不能以分隔符开头或结尾。

对于DNS主机名,是否需要用点号完全限定,或者“ my-local-server”是有效的注册表主机名?对于名称组件,我认为句点是有效的,这意味着“

team.user /

appserver”是有效的图像名称。如果注册表服务器在端口80上运行,因此映像名称中的主机名上不需要端口号,则似乎主机名与注册表服务器上的路径之间会存在歧义。我很好奇Docker如何解决这种歧义。

回答:

TL; DR:主机名必须在第.一个主机名之前包含dns分隔符或:端口分隔符/,否则代码假定您要使用默认注册表。


在仔细研究了代码之后,我遇到了distribution / reference /

reference.go,内容如下:

// Grammar

//

// reference := name [ ":" tag ] [ "@" digest ]

// name := [hostname '/'] component ['/' component]*

// hostname := hostcomponent ['.' hostcomponent]* [':' port-number]

// hostcomponent := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/

// port-number := /[0-9]+/

// component := alpha-numeric [separator alpha-numeric]*

// alpha-numeric := /[a-z0-9]+/

// separator := /[_.]|__|[-]*/

//

// tag := /[\w][\w.-]{0,127}/

//

// digest := digest-algorithm ":" digest-hex

// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]

// digest-algorithm-separator := /[+.-_]/

// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/

// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value

实际的实现是通过distribution / reference /

regexp.go中的regex实现的。

但是经过一番摸索之后,我发现除了该正则表达式外还有另一项检查(如果不包含a .或,则会出现大写主机名错误:)。我在docker /

distribution / reference /

normalize.go中将名称的实际拆分跟踪到以下内容:

// splitDockerDomain splits a repository name to domain and remotename string.

// If no valid domain is found, the default domain is used. Repository name

// needs to be already validated before.

func splitDockerDomain(name string) (domain, remainder string) {

i := strings.IndexRune(name, '/')

if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {

domain, remainder = defaultDomain, name

} else {

domain, remainder = name[:i], name[i+1:]

}

if domain == legacyDefaultDomain {

domain = defaultDomain

}

if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {

remainder = officialRepoName + "/" + remainder

}

return

}

对我而言,重要的部分是检查if语句中的第一个.:第一个之前的and

/。有了它,主机名就会从first之前分离出来/,而没有它,整个名字将被传递给默认的注册表主机名。

以上是 Docker镜像名称如何解析? 的全部内容, 来源链接: utcz.com/qa/416173.html

回到顶部