docker Push
を実行するとき、またはイメージをプルするとき、Dockerは、イメージ名にレジストリサーバーがあるかどうか、またはデフォルトのレジストリ(Docker Hubなど)のパス/ユーザー名であるかどうかをどのように判断しますか?
1.1画像仕様 から次のように見えます:
タグ
タグは、ユーザーが指定した説明的な名前を任意の単一の画像IDにマップするのに役立ちます。タグの値は、文字のセット[a-zA-Z_0-9]に制限されています。
リポジトリ
共通のプレフィックス(:の前の名前コンポーネント)の下にグループ化されたタグのコレクション。たとえば、my-app:3.1.4という名前でタグ付けされた画像では、my-appは名前のリポジトリコンポーネントです。リポジトリ名はスラッシュで区切られた名前コンポーネントで構成され、オプションでDNSホスト名がプレフィックスとして付けられます。ホスト名は標準のDNS規則に準拠している必要がありますが、_文字を含めることはできません。ホスト名が存在する場合は、オプションで、:8080の形式のポート番号を続けることができます。名前コンポーネントには、小文字、数字、および区切り文字を含めることができます。区切り文字は、ピリオド、1つまたは2つのアンダースコア、または1つ以上のダッシュとして定義されます。名前コンポーネントは、区切り文字で開始または終了することはできません。
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 の正規表現を介して行われます。
しかし、掘り下げて調べてみると、その正規表現以外にも別のチェックがあることがわかりました(.
または:
を含めないと、大文字のホスト名でエラーが発生します)。そして、名前の実際の分割を次のように追跡しました 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ステートメントの最初の.
の前にある:
と/
をチェックすることです。これを使用すると、ホスト名は最初の/
の前から分割され、それがない場合は、名前全体がデフォルトのレジストリホスト名に渡されます。
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/e98bc280c5349cb2919acecb0dfbfefa1ac4e5c3/src/docker/image_name.rb
いくつかのRubyテストは https://github.com/cyber-dojo/runner/blob/e98bc280c5349cb2919acecb0dfbfefa1ac4e5c3/test_server/image_name_test.rb