web-dev-qa-db-ja.com

Dockerイメージ名はどのように解析されますか?

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がそのあいまいさをどのように解決するのか興味があります。

15
BMitch

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ステートメントの最初の.の前にある:/をチェックすることです。これを使用すると、ホスト名は最初の/の前から分割され、それがない場合は、名前全体がデフォルトのレジストリホスト名に渡されます。

13
BMitch

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

0
Jon Jagger