将Docker镜像标签parsing为组件部分

规范的Docker镜像标签的格式如下:

[[registry-address]:port/]name:tag 

地址和端口可以省略,在这种情况下,Docker转到Docker Hub的默认registry。 例如以下全部有效:

 ubuntu:latest nixos/nix:1.10 localhost:5000/myfirstimage:latest localhost:5000/nixos/nix:latest 

我需要一些代码将这个string可靠地parsing到其组成部分。 然而,看起来不可能做到这一点,因为“名称”组件可以包含斜线。 例如下面的标签是不明确的:

 localhost/myfirstimage:latest 

这可能是Docker Hub上名为localhost/myfirstimage的映像,也可能是在localhost上运行的registry上名称为myfirstimage的映像。

有谁知道Docker如何parsing这种input?

我相信它可以毫不含糊地parsing。

据此

当前用于识别图像的语法如下所示:

[registry_hostname [:port] /] [user_name /](repository_name [:version_tag] | image_id)

本地主机是唯一允许使用的单一主机名称。 所有其他人必须包含一个端口(“:”)或多个部分(“foo.bar”,所以包含一个“。”)

在实践中,这意味着,如果您的泊坞窗图像标识符以localhost开头,则将针对在localhost:80上运行的registryparsing

 >docker pull localhost/myfirstimage:latest Pulling repository localhost/myfirstimage Error while pulling image: Get http://localhost/v1/repositories/myfirstimage/images: dial tcp 127.0.0.1:80: getsockopt: connection refused 

(使用Docker 1.12.0testing)

同样的“。”

 >docker pull a.myfirstimage/name:latest Using default tag: latest Error response from daemon: Get https://a.myfirstimage/v1/_ping: dial tcp: lookup a.myfirstimage on 127.0.0.1:53: no such host 

“:”

 >docker pull myfirstimage:80/name:latest Error response from daemon: Get https://myfirstimage:80/v1/_ping: dial tcp: lookup myfirstimage on 127.0.0.1:53: no such host 

所以你的parsing代码应该在第一个“/”之前查看子串,并检查它是否是“localhost” ,或者它包含“。”。 或以“:XYZ” (一个端口号)结尾,在这种情况下它是一个registry_hostname ,否则它是一个存储库名称 (username / repository_name)。

实现这个的Docker代码似乎位于这里: reference.go和service.go

 // splitReposSearchTerm breaks a search term into an index name and remote name func splitReposSearchTerm(reposName string) (string, string) { nameParts := strings.SplitN(reposName, "/", 2) var indexName, remoteName string if len(nameParts) == 1 || (!strings.Contains(nameParts[0], ".") && !strings.Contains(nameParts[0], ":") && nameParts[0] != "localhost") { // This is a Docker Index repos (ex: samalba/hipache or ubuntu) // 'docker.io' indexName = IndexName remoteName = reposName } else { indexName = nameParts[0] remoteName = nameParts[1] } return indexName, remoteName } 

(虽然我没有更详细的调查)