关于Docker镜像
- 仓库(Repository)
- 镜像仓库服务(Image Registry)
- 镜像仓库(Image Repository)
- 标签(Tag)
- 拉取镜像(Pull)
- 过滤docker image ls输出内容
- 搜索Docker Hub(Search)
- 分层
- 共享镜像层
- 分发散列值(Distribution Hash)
- 多层架构镜像
- 删除(Remove)
仓库(Repository)
镜像仓库服务(Image Registry)
Docker镜像存储在镜像仓库服务 当中。Docker客户端的镜像仓库服务是可配置的,默认使用Docker Hub。
镜像仓库(Image Repository)
镜像仓库服务包含多个镜像仓库。同样,一个镜像仓库中可以包含多个镜像,它们通常对应不同的版本。
官方和非官方镜像仓库
Docker Hub也分为官方仓库(Official Repository)和非官方仓库(Unofficial Repository)。
下图帮助理解:
拉取镜像命令的格式:
docker image pull <repository>:<tag>
标签(Tag)
- 一个镜像可以拥有多个标签
- 不能仅根据latest标签判断镜像为最新版本
-
docker image ls
会将相同镜像的不同标签分别列出,这是因为一个镜像可以根据用户需要设置多个标签,而标签就是存放在镜像元数据中的任意数字或字符串。
- 悬虚(dangling)镜像:没有标签的镜像。
出现悬虚镜像通常是因为构建了一个新镜像,然后为该镜像打了一个已经存在的标签。当此情况出现,Docker会构建新的镜像,然后发现已经有镜像包含相同的标签,接着Docker会移除旧镜像上面的标签,将该标签标在新的镜像之上。
拉取镜像(Pull)
- 拉取Docker Hub官方仓库中的镜像(默认)
docker image pull <repository>:<tag>
- 拉取Docker Hub 的非官方仓库中的镜像
docker image pull AAA/BBB:v2
解释:从Docker Hub里Docker账号ID为AAA
的BBB
库中下载标签为v2
的镜像 - 从第三方镜像仓库服务获取镜像(非Docker Hub),需要在镜像仓库名称前加上第三方镜像仓库服务的DNS名称。
假如从Google容器镜像仓库服务(GCR) 拉取AAA的BBB库中标签为v2的镜像docker pull gcr.io/AAA/BBB:v2
` - 根据摘要(Digest) 拉取镜像。
因为摘要是镜像内容的一个散列值,所以镜像内容的变更一定会导致散列值的改变。这意味着相同镜像摘要的是不可变的。
- 已知镜像的摘要,那么下次就可以使用摘要再次拉取这个镜像。这种方式可以确保准确拉取想要的镜像 。下图实验帮助理解:
解释:
假设我对ubuntu:latest
镜像做了修改并上传。由于标签没有变,仅凭标签无法区分修改前后的两个镜像。这时可以使用摘要来指定唯一的镜像。
-
docker image ls --digests
查看了实验镜像的摘要,即图中光标强调部分 -
docker image rm e4c5
删除了该镜像 -
docker image pull ubuntu@sha256:2b74...f05f
根据摘要拉取镜像 -
docker image ls --digests
查看镜像摘要,确定成功拉取了修改过的镜像。
过滤docker image ls输出内容
- Docker提供
--filter
参数来过滤docker image ls
命令返回的镜像列表内容
- 例如,只返回悬虚(dangling)镜像:
docker image ls --filter dangling=true
- Docker目前支持的过滤器:
-
dangling
:可以指定true 或者false ,仅返回悬虚镜像(true),或者非悬虚镜像(false)。 -
before
:需要镜像名称或者ID作为参数,返回在之前被创建的全部镜像。 -
since
:与before 类似,不过返回的是指定镜像之后创建的全部镜像。 -
label
:根据标注(label) 的名称或者值,对镜像进行过滤。docker image ls 命令输出中默认不显示标注内容。 - 其他的过滤方式可以使用
reference
例如使用reference
完成过滤并且仅显示标签为latest的镜像:docker image ls --filter=reference="*:latest"
- 也可以使用
--format
参数来通过Go模板对输出内容进行格式化 - 如果需要更复杂的过滤,可以使用OS或者Shell自带的工具,比如
Grep
或者AWK
-
-q
选项意为quiet(静默模式),使docker image ls
只输出镜像ID
搜索Docker Hub(Search)
docker search
命令允许通过CLI的方式搜索Docker Hub。该命令会搜索所有“NAME”字段中包含特定字符串的仓库
- CLI(Command Line Interface)即“命令行界面”
- “NAME”字段是仓库名称,包含了Docker ID,或者非官方仓库的组织名称
- 例如,执行
docker search ubuntu
命令的结果: - 上面返回的镜像中既有官方的也有非官方的。我们可以使用
--filter "is-official=true"
使返回内容只显示官方镜像。 - 也可以使用
--filter "is-automated=true"
只显示自动创建的仓库。 - 默认情况下,Docker只返回25行结果。但是可以指定选项
--limit
的参数来增加返回内容行数,最多为100行。
分层
- Docker镜像由一些松耦合的只读镜像层组成
- Docker负责堆叠这些镜像层,并且将它们表示为单个统一的对象
- 下图展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。
- 在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合。
- Docker通过存储引擎 (新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
- 下图展示了系统视角的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
共享镜像层
- 多个镜像之间会共享镜像层。这样可以有效节省空间并提升性能。
- Docker在Linux上支持很多存储引擎。每个存储引擎都有自己的镜像分层、镜像层共享以及写时复制(CoW)技术的具体实现。但是,其最终效果和用户体验是完全一致的。
下图展示了拉取两个镜像的过程:
注意那些以Already exists
结尾的行,这从侧面验证了共享镜像层机制。
分发散列值(Distribution Hash)
散列值(Hash)也被称为摘要(Digest)
- 在推送和拉取镜像的时候,都会对镜像层进行压缩来节省网络带宽以及仓库二进制存储空间。但是压缩会改变镜像内容,这意味着镜像的内容散列值在推送或者拉取操作之后,会与镜像内容不相符。
- 为避免该问题,每个镜像层同时会包含一个分发散列值(Distribution Hash)。这是一个压缩版镜像的散列值,当从镜像仓库服务拉取或者推送镜像的时候,其中就包含了分发散列值,该散列值会用于校验拉取的镜像是否被篡改过。
- 该模型也解决了随机生成的镜像ID与镜像层ID可能冲突的问题。
多层架构镜像
- 为了避免每次拉取镜像都需要手动对应主机架构,多架构镜像(Multi-architecture Image)出现了。
- 实现方式:
- Docker会维护一个称为 Manifest 列表的结构来管理多个镜像的不同平台和架构的版本。
- Manifest列表是指某个镜像标签支持的架构列表。其支持的每种架构,都有自己的Manifest定义,其中列举了该镜像的构成。
- 以Golang 官方镜像为例。 图左侧是Manifest列表,其中包含了该镜像支持的每种架构。Manifest列表的每一项都有一个箭头,指向具体的Manifest,其中包含了镜像配置和镜像层数据。
- 实践验证:
解释:docker container run --rm golang go version
命令:启动容器
-
--rm
选项:在容器退出后自动删除容器(可选) -
golang
参数:镜像库 -
go version
参数:启动后执行的命令
- 当在其它架构主机的docker上执行该命令时,结果将不再是
go version go1.21.3 linux/amd64
。
假如使用64位Windows,结果将会是go version go1.21.3 windows/amd64
这体现了多层架构镜像的功能。
删除(Remove)
Remove 的缩写是 rm
- 可以通过
docker image rm
命令从Docker主机删除镜像。 - 该操作会试图删除镜像以及相关的镜像层。对于被多个镜像共享的镜像层,只有当全部依赖该镜像层的镜像都被删除后,该镜像层才会被删除。
- 当镜像存在关联的容器时,不允许删除,除非使用
-f
选项。 - 删除全部镜像:
docker image rm $(docker image ls -q) -f
$
是 shell中的特殊字符,表示命令替换(command substitution)
命令替换允许将命令的输出作为命令行中的一个值进行替换。-q
意为quiet(静默模式),使docker image ls
命令只输出镜像ID
-
$(docker image ls -q)
参数:所有镜像的ID -
-f
选项:强制