关于docker:图像和存储库有什么区别?

What is the difference between an image and a repository?

我对Docker来说是个新手,并且遵循入门教程。在第7步,它说

type docker images command and press RETURN. The command lists all the images on your local system. You should see docker/whalesay in the list.

1
2
3
4
$ docker images
REPOSITORY           TAG         IMAGE ID            CREATED            VIRTUAL SIZE
docker/whalesay      latest      fb434121fc77        3 hours ago        247 MB
hello-world          latest      91c95931e552        5 weeks ago        910 B

但是第一列清楚地写着"存储库",而不是"图像名称"。我还注意到在其他人的机器上,由于一个图像可以有多个标签,所以这个列表通常包含重复的条目——每个标签对应一个条目。那么,这是图像列表、存储库列表、图像标记组合列表还是其他内容?图像和存储库有什么区别?

另外,考虑到图像和存储库是不同的,我如何只列出我的存储库?

这与容器无关。


是的,这是非常令人困惑的术语。

最简单的答案:

图像:单个图像。

存储库:图像的集合。

细节:

图:Image ID唯一引用的12位十六进制代码(如91C95931E552)。〔1〕

存储库:包含一个或多个图像。因此,hello-world存储库可以包含两个不同的图像:91c95931e5521234abcd5678

Image alias—我将Image alias定义为引用特定图像的别名。Image alias的格式是repository:tag。这样,您就可以使用人性化的别名,如hello-world:latest,而不是12位代码。

例子:

假设我有这些图片:

1
2
3
4
5
REPOSITORY           TAG         IMAGE ID
docker/whalesay      latest      fb434121fc77
hello-world          latest      91c95931e552
hello-world          v1.1        91c95931e552
hello-world          v1.0        1234abcd5678

存储库有:docker/whalesayhello-world

图像有fb434121fc7791c95931e5521234abcd5678。请注意,第2行和第3行具有相同的Image ID,因此它们是相同的图像。

图像别名为:

1
2
3
4
docker/whalesay:latest
hello-world:latest
hello-world:v1.1
hello-world:v1.0

因此,hello-world:latesthello-world:v1.1只是同一图像的两个别名。

其他详细信息:

  • Repository name格式还可以预先设置可选的用户或命名空间,这在使用Docker Hub之类的公共注册表时非常有用。如docker/whalesay。否则,您将有很多存储库名称冲突。

  • 如果在引用图像别名时不使用tag,它将自动添加:latest。因此,当您指定hello-world时,它将被解释为hello-world:latest。警告:latest实际上并不意味着什么特别的东西,它只是一个默认标签。

  • [1]实际上,完整的图像ID是一个64位的十六进制代码,被截断为12位,但您不需要关心这个问题。


引自官方码头文件:

A repository potentially holds multiple variants of an image.

(请参阅:https://docs.docker.com/userguide/dockerimages)

这意味着:Docker映像可以属于存储库,例如,当它被推送到Docker注册表时(使用docker push my/reporitory:version1)。另一方面,存储库包含图像的多个版本(=不同的标记)。因此,当您构建新版本的映像时,可以给它一个标签(docker tag 518a41981a6a my/reporitory:version2并将其作为下一个版本(docker push my/reporitory:version2推送到存储库中)。

下面是Docker文档中的一个示例(请参见上面的链接)。如您所见,它显示了一个名为ouruser/sinatra的存储库,其中包含同一映像的各种版本(latestdevelv2

1
2
3
4
5
$ docker images ouruser/sinatra
REPOSITORY          TAG     IMAGE ID      CREATED        VIRTUAL SIZE
ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB
ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB

在您的示例中,您有两个存储库(docker/whalesayhello-world,其中只包含一个标记图像(称为latest,这意味着实际上没有标记,并且显示了最新的图像)。


这里最容易定义几个术语,因为它们都相互关联:

图片:这是文件系统层和元数据,用于以运行容器的方式打包应用程序。每个图像必须在Docker引擎上有一个ID。

参考:这是指向图像的指针。有不同类型的引用,或者只是映像ID,通常是存储库和标记,有时您将使用sha256哈希而不是可变标记来固定到特定的校验和。重要的是,您可以有多个指向同一图像的指针,并且不需要对图像ID以外的图像进行任何引用。删除引用时,Docker将只删除该指针,除非它是指向该图像ID的最后一个指针。

注册表:这是一个保存图像的服务器。类似于Git服务器如何保存源代码,或者二进制文件的工件服务器,注册表是您推送和拉取图像的地方。

存储库:注册表服务器上图像目录的路径是存储库。如果不使用默认的Docker Hub注册表,这包括注册表主机名和端口。在图像引用中,此存储库是最后一个冒号和标记之前的部分。

标签:存储库中的特定图像。如果不指定标记,Docker将默认为标记名"latest"。这是最后一个冒号后面的部分,通常用于版本号。

举个例子:

1
registry-server:5000/team/service-a:build-42
  • "registry server:5000"是要在其中推/拉此映像的注册表服务器名称(和端口)。

  • "注册表服务器:5000/team/service-a"是存储库。

  • "build-42"是标签。

  • "registry server:5000/team/service-a:build-42"是一个引用。

与其他系统不同的是,推拉到服务器,然后指定要发送到服务器的文件,推拉到注册表服务器的Docker映像和从注册表服务器的Docker映像使用一个引用来定义映像的目标和源,该引用包含以该名称命名的存储库和标记。因此,要将图像推送到不同的位置,您可以使用新的存储库和标记(使用docker tag命令)创建对同一图像的新引用,然后针对该引用运行push命令。

通常,当某人引用"图像名称"时,他们引用的要么是存储库名称(如果要单独指定标记),要么是可用于拉或推图像的完整引用。

how can I just list my repositories?

1
docker image ls --format '{{.Repository}}' | sort -u

我加入了sort -u来消除输出重复,因为您可能有多个具有相同存储库和不同标签的图像。


通过使用给定的Dockerfile运行docker build生成图像,并通过其ID进行标识。

存储库和标记只是在有意义的层次结构/体系结构中命名和组织图像的手段。

  • 存储库通常包含多个相关图像

  • 一个图像可以进入多个存储库

下面,从这个答案中,详细解释了docker images输出(这可能是他们应该放在文档中的内容):

  • IMAGE ID is the first 12 characters of the true identifier for an image. You can create many tags of a given image, but their IDs will
    all be the same (as above).

  • The value in the REPOSITORY column comes from the -t flag of the docker build command, or from docker tag-ing an existing image.
    You're free to tag images using a nomenclature that makes sense to
    you, but know that docker will use the tag as the registry location in
    a docker push or docker pull.

  • The full form of a tag is [REGISTRYHOST/][USERNAME/]NAME[:TAG]. For ubuntu above, REGISTRYHOST is inferred to be
    registry.hub.docker.com. So if you plan on storing your image called
    my-application in a registry at docker.example.com, you should tag
    that image docker.example.com/my-application.
  • The TAG column is just the [:TAG] part of the full tag. This is unfortunate terminology.

  • 我将试图以一种非常尖锐和清晰的方式来解释这一点。

    Docker图像名称Docker图像本身没有名称。它有一个ID、存储库和一个标记(根据Docker Docs,它是目标图像的代名词,而不是英文单词标记)。所以,每次我们引用docker image name(创建、运行、删除、拉拽等)时,我们实际上都会引用image repository:tag(目标映像),我们经常会忽略tag部分(只写repository名称,我们将其视为映像名称),这时docker假定默认标记为EDOCX1(0(即目标图像最新)

    Docker存储库Docker在构建/创建图像时,为该图像和图像本身创建存储库,然后将当前(:latest标记)图像添加到该存储库中。根据MarkoLuksa的《Kubernetes in Action》一书,图像标签使我们能够在同一图像名下拥有同一图像的多个版本(标签)。所以我们可能会让myapp:latest、myapp:v1、myapp:v2都在一个标识符下,这里的每个标签都指向一个特定的目标图像,即同一应用程序的特定Snapshop/版本。这就是Docker命名图像存储库并将差异化作业保留为标签的原因,因为一个存储库应该(并且必须)包含不同版本的AME应用程序。

    因此,如果我们运行docker build -t A .,docker实际上会创建一个图像存储库A和图像本身(带有:最新标签)。然后,它会将该映像添加到存储库A中。稍后,我们将能够推/拉该映像的特定快照。

    P.S.我们用来调用docker image name的方法是(并且可以假定为)实际上是docker image repository[:tagname],后者是可选的,默认情况下为:latest

    您可以测试所有这些,并通过尝试在不指定标记的情况下删除图像,以及当图像存储库中没有默认的最新图像时,向自己证明这一点。只要运行docker rmi myimage,你就会看到,docker会抱怨,说Error: No such image: myiamge默认(当你不提供标签时),它假定并暗示:最新标签。

    希望这对这个问题有更多的启发。