Docker 图像和它的存储库什么时候会有不同的名称?

When would a Docker image and its repository have different names?

docker tag命令的标准用法是:

docker tag <image> <username>/<repository>:<tag>

例如:docker tag friendlyhello john/get-started:part1.

来自Java-land,我习惯Maven/Gradle-style坐标group:artifact:version,所以对我来说,imagerepository 成为同一个:

image 是您正在生成的工件,在 Java 领域中,生成的工件与其代码所在的源代码库之间通常存在 1:1 关系.所以对我来说,命令只是:

更有意义
docker tag <username>/<repository>:<tag>

例如:docker tag john/get-started:part1,其中 john 是 username/group,get-started 是 artifact/repo,part1 是 tag/version.

要清楚:不是问图像和存储库之间的区别!我知道存储库是存储图像的位置,我知道图像是一个 Docker 可执行文件,由 Docker 化的应用程序及其依赖项组成。但是从命名的角度来看,我很困惑 why/when 它们应该彼此不同。

所以我问:从命名约定的角度来看,imagerepository 有什么区别?例如,如果我想制作自己的 MySQL Docker 图像,我会选择制作名为“myapp-db”的图像,这样也会是它所在的存储库的名称(smeeb/myapp-db:v1smeeb/myapp-db:v2 等)。

那么在什么情况下are/should imagerepository名字会不同呢?

一种情况下,如果您使用的图像已过时,则图像的标签可能与存储库名称不同。

例如,您下载 运行 一张 MySQL:5 图片。当您拉取更新版本的 MySQL:5 图像时,此容器仍然是 运行ning。那时旧图像将被取消标记(只能通过其哈希识别),但不会被删除,因为它仍在被 运行ning MySQL 容器使用。

另一种情况是,您可以在构建新图像时使用中间图像。基本上每一行都会作为一个新图像提交,但它们不会以您指定的名称命名为最终图像名称。

使用 docker tag 时,您甚至不必将图像名称用作第一个参数。您甚至可以使用要标记的图像的哈希值作为第一个参数,因此它比 namespace/repository:tag.

更灵活

必须说明图像和存储库之间的区别:

图像是标记的存储库。这就是 的区别。 <username> 是存储库名称的一部分。

来自overview of the Docker Registry Distribution API

Classically, repository names have always been two path components where each path component is less than 30 characters. The V2 registry API does not enforce this. The rules for a repository name are as follows:

A repository name is broken up into path components. A component of a repository name must be at least one lowercase, alpha-numeric characters, optionally separated by periods, dashes or underscores. More strictly, it must match the regular expression [a-z0-9]+(?:[._-][a-z0-9]+)*. If a repository name has two or more path components, they must be separated by a forward slash ("/"). The total length of a repository name, including slashes, must be less than 256 characters.

只需为您的图片和标签使用有意义的名称。你可以有 smeeb/myappsmeeb/myapp-db。对于标签,惯例是使用版本标签和一个 latest 标签。

首先是先决条件:标签是指向图像的指针,图像是 docker 用于制作容器的配置和层清单的 sha256 引用。这意味着 friendlyhello 不是图像的名称,它是指向图像的标签。图片是id,类似于c75bebcdd211.....

接下来,每个图像可以有零个、一个或多个标签都指向它。当它没有任何指向它的标签时,这被称为悬挂图像。如果您构建带有标签的图像,然后重建它,就会发生这种情况。之前的图像现在未标记,因为标记指向新图像。同样,您可以让标签 image:latestimage:v1image:1.0.1myrepo:5000/image:1.0 都指向相同的图像 ID。

标签有双重用途。它们可以是为了方便。但是 docker pushdocker pull 也使用它们来查找发送或检索包裹的位置。如果你不做推或拉,那么你可以随意命名,没有人会知道其中的区别。但是,如果您确实想将其存储在注册表中,则标签需要标识哪个注册表或默认的 docker 集线器。并且该标记还需要标识注册表上的路径,称为存储库,以及冒号后的版本控制。

一个令人困惑的地方是存储库名称末尾的短名称通常称为 "image name",而冒号后的版本控制通常称为 "tag",我认为这如果您忘记了这些术语曾经像那样超载,就更容易理解。


现在有了所有这些背景(抱歉,内容太多),这里是对问题的一些更正:

而不是:

docker tag <image> <username>/<repository>:<tag>

将语法视为:

docker tag <source> <tag>

其中 <source> 可以是图像 ID,或其他标签名称。这意味着以下命令没有意义:

docker tag <username>/<repository>:<tag>

因为 docker tag 需要一个来源来标记,并且它对您当前正在处理的图像没有上下文感。


最后,为什么要为图像使用存储库名称以外的名称,以下是我遇到的几个原因:

  1. 图像不会被推送到存储库。它可能用于本地测试,或工作流程中的中间步骤,或者您在同一系统上构建和 运行 您的图像。

  2. 同一张图片可以有多个名称。 registry/repo/image:v1registry/repo/image:v1.0.1 是一个常见的例子。我还将在特定环境中使用 registry/repo/image:STAGE 标记当前图像,以注意它已通过开发和 CI 并且现在处于暂存环境中。

  3. 您可能在注册表之间移动图像。我们从 hub.docker.com 中提取图像并使用本地注册表在本地重新标记它们。这既为我们提供了本地缓存,也为我们提供了一种控制何时将基础图像更新到下一个版本的方法。这比在产品发布过程中更新映像更可取。

  4. 我还使用标签来覆盖上游图像。因此,我无需针对上游图像的问题更改所有构建脚本,而只需进行更改并使用上游名称对其进行标记即可。然后只要我不 运行 拉那个 docker 主机,构建就会 运行 使用我修改后的基础映像。