码头图像名称是如何分析的?

在执行Docker docker push或拉取图像时,Docker如何确定映像名称中是否存在注册服务器,或者它是否为默认注册表(例如Docker Hub)上的路径/用户名?

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

标签

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

知识库

在一个公共前缀下分组的标签集合(在:)之前的名称组件)。 例如,在名称为my-app:3.1.4的图像中,my-app是名称的Repository组件。 存储库名称由斜杠分隔的名称组件组成,可选地以DNS主机名作为前缀。 主机名必须遵守标准DNS规则,但不得包含_字符。 如果存在主机名,则可以选择使用格式为8080的端口号。 名称组件可能包含小写字符,数字和分隔符。 分隔符定义为句点,一个或两个下划线或一个或多个破折号。 名称组件不能以分隔符开始或结束。

对于DNS主机名,它是否需要完全限定点,或者是“my-local-server”是有效的注册表主机名? 对于名称组件,我将周期视为有效,这意味着“team.user / appserver”是有效的图像名称。 如果注册表服务器在端口80上运行,因此图像名称中的主机名不需要端口号,似乎主机名和注册表服务器上的路径之间会有不明确的地方。 我很好奇Docker如何解决这个模糊问题。


TL; DR:主机名必须包含一个. dns分隔符或第一个/之前的a : port分隔符,否则代码将假定您需要默认注册表。


在深入了解代码之后,我遇到了以下分发/参考/ 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中的正则表达式。

但也有一些挖掘和戳,我发现还有另一项检查除此之外,正则表达式(你会得到一个大写的主机名的错误,如果你不不包括.: )。 我在docker / reference.go中追踪了以下名称的实际拆分:

func splitHostname(name string) (hostname, remoteName string) {
    i := strings.IndexRune(name, '/')
    if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {
        hostname, remoteName = DefaultHostname, name
    } else {
        hostname, remoteName = name[:i], name[i+1:]
    }
    if hostname == LegacyDefaultHostname {
        hostname = DefaultHostname
    }
    if hostname == DefaultHostname && !strings.ContainsRune(remoteName, '/') {
        remoteName = DefaultRepoPrefix + remoteName
    }
    return
}

对我来说,重要的部分是检查.:在第一个/在第一个if语句之前。 有了它,主机名将从第一个/之前分离出来,如果没有它,整个名称将传递给默认的注册表主机名。


https://github.com/moby/moby/blob/master/image/spec/v1.1.md中的image-spec现在已经更新,说明标记限制为128个字符。

PR线程在https://github.com/docker/distribution/issues/2248

一些Ruby代码在这里https://github.com/cyber-dojo/runner/blob/master/server/src/valid_image_name.rb

一些Ruby测试在这里https://github.com/cyber-dojo/runner/blob/master/server/test/src/valid_image_name_test.rb

链接地址: http://www.djcxy.com/p/92257.html

上一篇: How are docker image names parsed?

下一篇: changing a config value depending on test method