CONTAINERS-REGISTRIES 配置文件是用于容器镜像注册表的全局配置文件,其格式为 TOML。
TOML(Tom's Obvious, Minimal Language)是一种易读、强类型的配置文件格式,设计目标是 “为人设计的配置语言”,比 JSON 更贴近手写习惯,比 YAML 更简洁无歧义,被广泛用于容器配置(如 Podman 的 registries.conf)、编程语言配置(如 Rust/Cargo)、工具链配置(如 Hugo、Terraform)等场景。
容器引擎会优先使用 $HOME/.config/containers/registries.conf(若存在),否则将使用 /etc/containers/registries.conf。
unqualified-search-registries:按顺序尝试拉取未限定镜像时使用的 host[:port] 注册表数组(什么是未限定镜像,即短名称镜像,如 redis,它的全称为 docker.io/library/alpine/redis:latest)。
credential-helpers:用于作为外部凭证存储的默认凭证助手数组。请注意,containers-auth.json 是保留值,用于使用 containers-auth.json(5) 中指定的身份验证文件。若未指定任何凭证助手,则默认设置为 ["containers-auth.json"]。
additional-layer-store-auth-helper:包含辅助程序二进制名称的字符串。启用后,每次通过 docker:// 传输协议读取镜像时,将向附加层存储传递注册表凭证,使其能够访问私有注册表。更多细节请参阅下文“启用额外层存储以访问私有注册表”章节。
配置的主体以 [[registry]] TOML 表数组的形式呈现;因此,不同注册表之间的设置可能存在差异,同一注册表内不同命名空间/存储库之间的设置也可能不同。
根据镜像名称,基于其前缀字段选择单个 [[registry]] TOML表。
prefix:用户指定镜像名称的前缀,即采用以下格式之一:
host[:port]
host[:port]/namespace[/namespace…]
host[:port]/namespace[/namespace…]/repo
host[:port]/namespace[/namespace…]/repo(:_tag|@digest)
[*.]host
用户指定的镜像名称必须以特定前缀开头(并以适当的分隔符继续),才能被特定的 [[registry]] TOML 表考虑;(仅)使用匹配最长的 TOML 表。它还可以包含通配符子域,格式为 *.example.com。通配符应仅出现在开头,如上述格式所示。其他情况将失效。例如:*.example.com 有效,但 example.*.com、*.example.com/foo 及 *.example.com:5000/foo/bar:baz 均无效。需注意 * 可匹配任意数量的子域名,因此 *.example.com 将匹配 bar.example.com、foo.bar.example.com 等域名。
示例:
unqualified-search-registries = ["example.com"] [[registry]] prefix = "example.com/foo" insecure = false blocked = false location = "internal-registry-for-example.com/bar"
特殊情况:prefix 字段可省略,此时默认采用 location 字段(详见下文)的值。
insecure:true 或 false。默认情况下,容器运行时从注册表获取镜像时需要 TLS 加密。若设置为 true,则允许使用未加密的 HTTP 以及使用未受信任证书的 TLS 连接。
blocked:true 或 false。若为 true,则禁止拉取名称匹配的镜像。
用户指定的镜像引用本质上是一个“逻辑”镜像名称,始终用于命名镜像。默认情况下,镜像引用还会直接指定要使用的注册表和仓库,但可通过以下选项将底层访问重定向至不同的注册表服务器或位置(例如:在无需修改 Dockerfile 的情况下支持无网络访问的配置,或增加冗余)。
location:接受与前缀字段相同的格式,用于指定前缀为根的命名空间的物理位置。
默认情况下,该值等同于前缀(此时可省略前缀,且 [[registry]] TOML 表仅能指定 location)。
示例:
prefix = "example.com/foo" location = "internal-registry-for-example.com/bar"
对镜像 example.com/foo/myimage:latest 的请求实际上会与内部注册表 internal-registry-for-example.com/bar/myimage:latest 中的镜像匹配。
若使用包含通配符的前缀(格式:*.example.com)进行子域匹配,位置字段可留空。此时将执行前缀匹配,但不进行引用重写。原始请求的镜像字符串将保持不变,但其他设置(如不安全/被封锁/镜像站点规则)仍会应用于匹配的镜像。
示例:
prefix = "*.example.com"
对镜像 blah.example.com/foo/myimage:latest 的请求将按原样使用。但其他设置(如不安全/被阻止/镜像)将应用于匹配的镜像。
mirror :一个TOML表数组,用于指定前缀根命名空间(即当前 [[registry]] TOML表)的(可能不完整的)镜像。
镜像按指定顺序尝试连接;首个可连接且包含镜像的镜像将被采用(若所有镜像均无镜像,则最后尝试由 registry.location 字段指定的主存储位置,或使用用户未修改的参考路径)。
镜像数组中的每个 TOML 表可包含以下字段:
location: 与 [[registry]] TOML 表格中指定的语义相同
insecure: 与 [[registry]] TOML 表格中指定的语义相同
pull-from-mirror: all, digest-only 或 tag-only。若设置为“digest-only”模式,镜像服务器仅用于摘要拉取。通过标签拉取镜像时,可能因拉取源端点不同而获得不同镜像。限制镜像仅用于摘要拉取可避免此问题。若设置为“tag-only”,镜像仅用于标签拉取。对于更新及时但资源消耗较高的镜像(即使标签变更也不易失效),不应将其用于摘要引用。默认值为“all”(或留空),此时镜像将同时用于摘要拉取和标签拉取,除非主注册表配置了mirror-by-digest-only选项。需注意:此项镜像级设置仅在主注册表未配置mirror-by-digest-only时才允许使用。
mirror-by-digest-only : true 或 false。若为true,则仅当镜像引用包含摘要时,镜像才会在拉取过程中使用。注意:若所有镜像均配置为仅摘要模式,则标签引用的镜像将仅使用主注册表;若所有镜像均配置为仅标签模式,则摘要引用的镜像将仅使用主注册表。
通过摘要引用镜像可确保始终使用同一镜像(而通过标签引用镜像可能导致不同注册表返回不同镜像,若标签映射出现不同步)。
注意:重定向和镜像功能目前仅在读取单个镜像时生效,不适用于向注册表推送数据或在注册表中执行其他类型的查找/搜索操作。此机制未来可能调整。
使用未限定搜索注册表会导致歧义,因为无法确定通过短名称引用的特定镜像将从哪个注册表中获取。
如本手册页末注释所述,使用短名称存在遭遇注册表命名空间被占用的风险。若未限定搜索的注册表设置为[“registry1.com”, “registry2.com”],攻击者可能接管registry1.com的命名空间,导致镜像被从registry1.com而非预期来源registry2.com拉取。
虽然强烈建议始终使用完全限定的镜像引用,但现有部署中使用的短名称可能难以更改。为规避上述歧义,可配置所谓的短名称别名,使其指向完全限定的镜像引用。
短名别名可在 [aliases] 表中配置,格式为 "name"="value",其中左侧名称为短名(例如“image”),右侧值为完全限定的镜像引用(例如“registry.com/namespace/image”)。请注意,“name”和“value”均不可包含标签或摘要。此外,“name”必须是短名称,因此不能包含注册表域名或指向本地主机。
在解析短名称时,系统将使用配置的别名表进行解析。若找到匹配的别名,则直接采用该别名,不再继续查询未限定搜索注册表列表。若未找到匹配别名,则可通过下文所述的短名称模式选项控制后续行为。
注意,在别名解析过程中,用户指定的短名称会去除标签和摘要。因此,“image”、“image:tag” 和 “image@digest” 均解析为同一别名(即 “image”)。被移除的标签和摘要将在后续解析后附加到最终别名上。
请注意,即插即用配置文件(参见 containers-registries.conf.d(5))可根据文件加载顺序覆盖别名。若别名的“value”字段为空(即“”),该别名将被清除。但需注意,单个配置文件中同一“name”仅可出现一次。
short-name-mode 选项支持三种模式来控制短名解析的行为:
enforcing: 如果只设置了一个未限定搜索的注册表,就使用它,因为不存在歧义。如果有多个注册表,且用户程序正在终端中运行(即标准输出和标准输入是 TTY),则提示用户从指定的搜索注册表中选择一个。如果程序不在终端中运行,这种歧义就无法解决,从而会导致错误。
permissive: 其行为与 enforcing 模式类似,但如果程序不在终端中运行,不会导致错误。相反,会退回到使用所有未限定搜索的注册表。
disabled: 不提示就使用所有未限定搜索的注册表。
如果完全未指定 short-name-mode 或使其为空,则默认采用 permissive 模式。如果用户指定的短名称尚未设置别名,那么在成功拉取后,enforcing 模式和 permissive 模式(若有提示)会记录一个新别名。请注意,对于 root 用户,所记录的别名将写入 /var/cache/containers/short-name-aliases.conf,以便清晰区分可能由人工编辑的 registries.conf 文件和机器生成的 short-name-aliases.conf。需要注意的是,无 root 权限的用户会使用 $HOME/.cache。如果某个别名既在 registries.conf 文件中指定,又在机器生成的 short-name-aliases.conf 中指定,那么 short-name-aliases.conf 文件具有更高的优先级。
Docker Hub(即docker.io)的处理方式很特殊:如果未定义其他特定命名空间(例如对于 docker.io/namespace/image),那么每次推送和拉取操作在内部都会被规范化为加上 /library。
(请注意,上述描述的规范化恰好与Docker的行为一致。)
这意味着拉取 docker.io/alpine 会在内部被转换为 docker.io/library/alpine。而拉取 docker.io/user/alpine 则不会被重写,因为这已经是正确的远程路径。。
因此,要重新映射或镜像(隐含的)/library命名空间中的docker.io镜像(或整个命名空间),此配置文件中的prefix(前缀)和location(位置)字段必须明确包含该/library命名空间。例如,应使用prefix = "docker.io/library/alpine",而不是prefix = "docker.io/alpine"。后者会匹配docker.io/alpine/*仓库,但不会匹配docker.io/[library/]
因此,若要重映射或镜像(隐含的)/library 命名空间(或整个命名空间)中的 docker.io 镜像,该配置文件中的前缀(prefix)和位置(location)字段必须明确包含该 /library 命名空间。例如应设置 prefix="docker.io/library/alpine",而非 prefix="docker.io/alpine"。后者将匹配 docker.io/alpine/* 仓库,但不会匹配 docker.io/[library/]alpine 镜像。
unqualified-search-registries = ["example.com"] [[registry]] prefix = "example.com/foo" insecure = false blocked = false location = "internal-registry-for-example.com/bar" [[registry.mirror]] location = "example-mirror-0.local/mirror-for-foo" [[registry.mirror]] location = "example-mirror-1.local/mirrors/foo" insecure = true [[registry]] location = "registry.com" [[registry.mirror]] location = "mirror.registry.com"
详细说明:
1、无前缀镜像的默认搜索规则
unqualified-search-registries = ["example.com"]
表示当你拉取无仓库前缀的镜像时(如 podman pull alpine),容器工具会自动为镜像补全前缀 example.com/,即实际拉取 example.com/alpine。
2、自定义仓库规则1:精准匹配 example.com/foo 前缀的镜像
[[registry]] prefix = "example.com/foo" # 匹配前缀:所有以 example.com/foo 开头的镜像 insecure = false # 强制HTTPS:访问该仓库必须用HTTPS(拒绝HTTP/自签名证书) blocked = false # 允许访问:不拉黑该仓库 location = "internal-registry-for-example.com/bar" # 地址映射:拉取 example.com/foo/xxx 时,实际访问 internal-registry-for-example.com/bar/xxx [[registry.mirror]] location = "example-mirror-0.local/mirror-for-foo" # 镜像加速器1:优先从这个镜像地址拉取 [[registry.mirror]] location = "example-mirror-1.local/mirrors/foo" # 镜像加速器2:加速器1失败时,尝试这个地址 insecure = true # 加速器2允许HTTP:该镜像地址可走非HTTPS
当你执行 podman pull example.com/foo/nginx 时:
容器工具先匹配到 prefix = "example.com/foo" 的规则;
优先尝试第一个镜像加速器 example-mirror-0.local/mirror-for-foo/nginx(强制 HTTPS,因为该镜像未单独设 insecure,继承父级 false);
若加速器 1 失败,尝试第二个镜像加速器 example-mirror-1.local/mirrors/foo/nginx(允许 HTTP,因为该镜像单独设 insecure = true);
若所有镜像都失败,最终访问真实地址 internal-registry-for-example.com/bar/nginx(强制 HTTPS)。
3、自定义仓库规则 2:无前缀的仓库(默认匹配所有未命中的镜像)
[[registry]] location = "registry.com" # 无prefix,匹配所有未被其他规则覆盖的镜像 [[registry.mirror]] location = "mirror.registry.com" # 该仓库的镜像加速器:拉取 registry.com/xxx 时,优先走 mirror.registry.com/xxx
所有未被 example.com/foo 前缀匹配的镜像(如 registry.com/redis),会使用此规则:
拉取 registry.com/redis 时,优先尝试镜像加速器 mirror.registry.com/redis;
加速器失败则访问原仓库 registry.com/redis;
未显式设置 insecure/blocked,默认值为 insecure = false(强制 HTTPS)、blocked = false(允许访问)。
鉴于上述情况,拉取 example.com/foo/image:latest 将会尝试:
example-mirror-0.local/mirror-for-foo/image:latest
example-mirror-1.local/mirrors/foo/image:latest
internal-registry-for-example.com/bar/image:latest
按顺序,并使用第一个存在的。
请注意,镜像仅与当前的 [[registry]] TOML 表相关联。如果使用上面的示例,拉取镜像 registry.com/image:latest 将只会访问 mirror.registry.com,而与 example.com/foo 相关联的镜像将不会被考虑。
additional-layer-store-auth-helper 选项允许将注册表凭据传递给额外层存储,以便它能够访问私有注册表。
通过额外层存储访问私有注册表时,需要提供一个辅助二进制文件。此辅助二进制文件通过 additional-layer-store-auth-helper 选项进行注册。每次使用 docker:// 传输读取镜像时,指定的辅助二进制文件都会被执行,并通过标准输入以以下格式接收注册表凭据。
{
"$image_reference": {
"username": "$username",
"password": "$password",
"identityToken": "$identityToken"
}
}$image_reference 的格式为 $repo{:$tag|@$digest} 。
额外的层存储可以使用这个辅助二进制文件来访问私有注册表。
版本1格式仍受支持,但不支持使用注册表镜像、最长前缀匹配或位置重写。
TOML格式用于在三个类别下构建一个简单的注册表列表:registries.search、registries.insecure 和 registries.block。你可以使用逗号分隔的列表来列出多个注册表。
当容器运行时的调用者没有完整指定他们想要执行的容器镜像时,就会使用搜索注册表。这些注册表会被添加到指定容器镜像的前面,直到在某个注册表中找到该命名镜像为止。
注意,不安全的注册表可用于任何注册表,而不仅仅是在搜索项下列出的那些注册表。
registries.insecure 和 registries.block 列表与当前版本中的 insecure 和 blocked 字段含义相同。
以下示例配置定义了两个可搜索的注册表、一个不安全的注册表和两个被阻止的注册表:
[registries.search] registries = ['registry1.com', 'registry2.com'] [registries.insecure] registries = ['registry3.com'] [registries.block] registries = ['registry.untrusted.com', 'registry.unsafe.com']
我们建议始终使用包含注册服务器(完整域名)、命名空间、镜像名称和标签的完整镜像名称(例如:registry.redhat.io/ubi8/ubi:latest)。使用短名称时,始终存在被拉取镜像可能被伪造的固有风险。例如:用户期望从 myregistry.com 注册表拉取名为 foobar 的镜像。若 myregistry.com 未位于搜索列表首位,攻击者可在更靠前的注册表放置伪造的 foobar 镜像。此时用户将误拉取并运行攻击者植入的镜像与代码,而非预期内容。我们建议仅添加完全可信的注册库,即禁止未知或匿名用户创建任意名称账户的注册库。此举可防止镜像遭伪造、抢注或产生其他安全隐患。若必须使用此类注册库,应将其添加至列表末尾。
建议在拉取镜像时使用完全限定的镜像,因为这样目标 registry 是明确的。通过摘要拉取镜像(即 quay.io/repository/name@digest)能进一步消除标签的歧义。
containers-auth.json(5) containers-certs.d(5)
2019年12月,Tom Sweeney 添加了针对不合格镜像名称的警告 tsweeney@redhat.com
2019年3月,Sascha Grunert 添加了额外的配置格式 sgrunert@suse.com
2018年8月,Valentin Rothberg 将其重命名为 containers-registries.conf(5) vrothberg@suse.com
2018年6月,由Tom Sweeney更新 tsweeney@redhat.com
2017年8月,由Brent Baude最初编译 bbaude@redhat.com
原文地址:https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md