Jaybanuan's Blog

どうせまた調べるハメになることをメモしていくブログ

コンテナイメージの名前について調べたメモ

はじめに

コンテナイメージの名前について、厳密の考えると色々ややこしいので、調べてまとめてみようと思った。 しかし、泥臭い変換や補完があったりして、キレイにはまとまらず。 ただ、せっかく調べたのでメモは残しておく。

環境

Docker CLIを前提として、主に最新のドキュメントとソースコードを中心に情報を収集した。 Podman等の別のコンテナ実装や、KubernetesのようなPaaS上でコンテナを扱うときは、異なる仕様/挙動になるかもしれない。 コマンドラインでの試行や設定ファイルの確認は、以下の環境で実施している。

$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 20.04.3 LTS"

$ docker --version
Docker version 20.10.8, build 3967b7d

コンテナイメージの名前の構成要素

「コンテナイメージの名前」と書いてみたものの、正しい表現かどうかはよく分からない。 「イメージ名(image name)」と呼ばれることが多い気がするが、文脈によっては誤解しそうなので、ここではあえて「コンテナイメージの名前」と表記しておくことにする。 また、Docker CLIソースコードの中では「リファレンス(reference)」と呼ばれているようだ。

コンテナイメージの名前のフォーマットは、ざっくりとは以下のような感じ。

hostname:1234/path/name:1.0.0
\___________/ \_______/ \___/
   ドメイン       パス     タグ
\_____________________/
        リポジトリ

ドメインは省略可能で、省略した場合はDocker CLIだとregistry-1.docker.ioになるようだ。 個人的な感覚としては、「ドメイン」というよりは、Container Registryの「APIサーバ」という表現の方が、名が体を表しているように思う。

以下に、リポジトリとタグの例として、docker image lsの結果を挙げておく。 表示された表の1行目がリポジトリ、2行目がタグであることが分かる。

$ docker image ls
REPOSITORY              TAG       IMAGE ID       CREATED        SIZE
hello-world             latest    d1165f221234   6 months ago   13.3kB
quay.io/centos/centos   latest    300e315adb2f   9 months ago   209MB

なお、コンテナイメージの名前の正確なフォーマット(文法)は、ソースコード中のコメントより、以下の通り。 この文法の中では「リファレンス」と呼ばれている。

// Grammar
//
//  reference                       := name [ ":" tag ] [ "@" digest ]
//  name                            := [domain '/'] path-component ['/' path-component]*
//  domain                          := domain-component ['.' domain-component]* [':' port-number]
//  domain-component                := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
//  port-number                     := /[0-9]+/
//  path-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
//
//  identifier                      := /[a-f0-9]{64}/
//  short-identifier                := /[a-f0-9]{6,64}/

少々気になるのが、文法的にdomainpath-componentの区別に曖昧さがあり、このままだと「path-componentのつもりで書いたのにdomainと解釈された」ということが起こりそうだということ。 推測だが、どこかで「パーサがdomainと解釈したけど、本当にドメイン(=APIサーバ)なの?」という追加の検査をしていそうに思える。

ドメインの省略について

先ほど「省略した場合はDocker CLIだとregistry-1.docker.ioになるようだ」と書いたが、これはドキュメントから引っ張ってきた情報である。 しかし実際には、ドメインを省略した場合の、ドメインの決定方法は設定によって変更できるようだ。 例えば、調査した環境では、/etc/containers/registries.confというファイルに、省略したドメインを補完するための設定情報がある。

(略)
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
unqualified-search-registries = ["docker.io", "quay.io"]
(略)

また、コンテナイメージの名前にエイリアスをつけることができるようであり、これを利用して補完(というかマッピング)することもできる。 調査した環境では、エイリアス/etc/containers/registries.conf.d/000-shortnames.confで定義されていたので、その一部を以下に示しておく。

[aliases]
  # centos
  "centos" = "quay.io/centos/centos"
  # containers
  "skopeo" = "quay.io/skopeo/stable"
  "buildah" = "quay.io/buildah/stable"
  "podman" = "quay.io/podman/stable"
  # docker
  "alpine" = "docker.io/library/alpine"
  "docker" = "docker.io/library/docker"
  "registry" = "docker.io/library/registry"
  "hello-world" = "docker.io/library/hello-world"
  "swarm" = "docker.io/library/swarm"
  # Fedora
  "fedora-minimal" = "registry.fedoraproject.org/fedora-minimal"
  "fedora" = "registry.fedoraproject.org/fedora"
(以下略)

特別なパスlibrary/

DockerHub公認のコンテナイメージは特別扱いされており、パスがlibrary/で始まる。 例えば、上記のエイリアスの中にも含まれているが、docker.io/library/hello-world等がそれにあたる。 具体的な処理内容までは追いきれていないが、ソースコード中に、パスのプレフィックスlibrary/かどうかで条件分岐している処理が数カ所確認できた。

参考