何时Docker镜像和其仓库会有不同的名称?

6
< p > < code > docker tag 命令的标准用法为:

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

例如,docker tag friendlyhello john/get-started:part1
从Java领域来看,我习惯于Maven/Gradle风格的group:artifact:version坐标系。因此,在我看来,将imagerepository视为同一个概念是有道理的: image是您正在生成的构件,而在Java领域中,通常生成的构件与其源代码所在的存储库之间存在一对一的关系。因此,对我而言,命令应该只是:
docker tag <username>/<repository>:<tag>

例如:docker tag john/get-started:part1,其中john是用户名/组,get-started是构件/仓库,part1是标签/版本。
明确一点:我并不询问镜像和仓库之间的区别!我知道仓库是存储镜像的位置,而镜像则是由您的Docker化应用程序及其依赖项组成的可执行Docker。但就命名而言,我困惑于何时它们应该有所不同。
因此,我想问:从命名约定的角度来看,镜像和仓库之间有什么区别?例如,如果我想制作自己的MySQL Docker镜像,我会选择将镜像命名为“myapp-db”,那也将是它所在的仓库的名称(smeeb/myapp-db:v1,smeeb/myapp-db:v2等)。
那么,在什么情况下,镜像和仓库的名称应该不同呢?
3个回答

5
首先要说明的是,标签(tag)是指向镜像(image)的指针,镜像是配置和层的 sha256 引用,Docker 使用它们来创建容器。这意味着 `friendlyhello` 不是一个镜像的名称,它是指向镜像的标签。镜像是 id,就像 `c75bebcdd211...`。
其次,每个镜像可以有零个、一个或多个标签与之对应。当没有任何标签指向它时,称之为悬挂式镜像(dangling image)。如果您使用标签构建镜像,然后重新构建它,就会发生这种情况。以前的镜像现在已经取消了标记,因为标签指向新的镜像。同样地,您可以将标签 `image:latest`、`image:v1`、`image:1.0.1` 和 `myrepo:5000/image:1.0` 都指向相同的镜像 ID。
标签具有双重用途。它们可供方便使用。但它们也被 `docker push` 和 `docker pull` 用于查找要发送或检索包的位置。如果您不进行推送或拉取操作,那么您可以随意命名它,别人也不会知道任何区别。但是,如果您想将它存储到注册表中,则标签需要标识出哪个注册表(或默认的 Docker Hub)。该标签还需要标识出存储库后面的版本号。
令人困惑的一点是,存储库名称末尾的短名称通常称为“镜像名称”,冒号后面的版本控制通常称为“标签”。如果忘记这些术语曾经被重载,我认为这样理解会更容易些。
现在有了所有这些背景知识(抱歉,内容有点多),下面是对问题的一些纠正:
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 主机上运行拉取操作,就可以使用修改后的基础镜像运行构建。


1
如果您使用的图像已过时,可能会出现图像具有不同标记的情况。例如,您下载并运行MySQL:5图像。当您拉取新版本的MySQL:5图像时,该容器仍在运行。此时,旧图像将取消标记(仅通过其哈希值可识别),但不会被删除,因为正在运行的MySQL容器仍在使用它。
另一种情况是在构建新图像时可能会有中间图像。基本上,每个行都会作为一个新图像提交,但它们不会以您指定的最终图像名称命名。
使用docker tag时,您甚至不必将图像名称用作第一个参数。您甚至可以使用要标记的图像的哈希值作为第一个参数,因此比命名空间/存储库:标记更加灵活。

1

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

图像是一个带有标签的存储库。这是唯一的区别。<username>是存储库名称的一部分。

来自Docker Registry Distribution API概述:

传统上,存储库名称始终为两个路径组件,其中每个路径组件都小于30个字符。 V2注册表API不强制执行此规则。存储库名称的规则如下:

存储库名称被分解为路径组件。存储库名称的组成部分必须至少是一个小写字母数字字符,可以选择使用句点、破折号或下划线进行分隔。更严格地说,它必须匹配正则表达式[a-z0-9]+(?:[._-][a-z0-9]+)*。如果存储库名称具有两个或多个路径组件,则它们必须由正斜杠("/")分隔。存储库名称的总长度(包括斜杠)必须小于256个字符。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接