当前位置: 首页 > 面试题库 >

Docker镜像名称如何解析?

汝楷
2023-03-14
问题内容

在做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 镜像 docker pull apache/shardingsphere-proxy 手动构建 Docker 镜像(可选) git clone https://github.com/apache/shardingsphere mvn clean install cd shardingsphere-distribution/shardingsphere-proxy-dist

  • 本文向大家介绍详解Docker如何启动一个Centos镜像,包括了详解Docker如何启动一个Centos镜像的使用技巧和注意事项,需要的朋友参考一下 接着上文,我们下载完成一个Centos镜像之后,开始启动 #运行命令 这样就能启动一个一直停留在后台运行的Centos了。如果少了/bin/bash的话,Docker会生成一个Container但是马上就停止了,不会一致运行即使有了-d参数。 然后

  • 本文向大家介绍Docker镜像构建原理解析(不装docker也能构建镜像),包括了Docker镜像构建原理解析(不装docker也能构建镜像)的使用技巧和注意事项,需要的朋友参考一下 在devops流程里面 构建镜像是一个非常重要的过程,一般构建镜像是写dockerfile文件然后通过docker client来构建的image。 docker client 会先检查本地有没有image,如果没有

  • 以下步骤指导您构建自己的Envoy二进制文件,并将其放入干净的Ubuntu容器中。 第1步:构建Envoy 使用envoyproxy/envoy-build编译Envoy。该镜像具有构建Envoy所需的全部软件。在您的Envoy目录中执行如下命令: $ pwd src/envoy $ ./ci/run_envoy_docker.sh './ci/do_ci.sh bazel.release' 执

  • 官方最佳实践文档 Best practices for writing Dockerfiles 明确指定镜像版本 构建镜像时,建议明确指定包含版本或者其他辅助信息的tag。 如果不指定镜像tag,默认会使用latest。这种方式不利于版本管理,对应用启动速度也有一定影响(每次启动应用实例时,都需要去镜像仓库检查镜像是否更新) 减小镜像大小 使用alpine版本的基础镜像 alpine是一个高度精简

  • 我阅读了Docker映像规范v1.2.0。上面说: 层由其序列化表示的加密哈希引用。这是用于传输层的tar存档上的SHA256摘要,表示为256位的十六进制编码,例如,SHA256:A9561EB1B190625C9ADB5A9513E72C4DEDAFC1CB2D5236C9A6957DFD5A9。层必须重复打包和解包,以避免更改层ID,例如使用tar split保存tar标头。请注意,用作层I