docker镜像详解

目录

什么是docker镜像

Docker镜像是Docker容器的基础组件,它包含了运行一个应用程序所需的一切,包括代码、运行时环境、系统工具、库和依赖等。Docker镜像的本质,可以分为以下几个方面来解释。

  1. 文件系统层:Docker镜像是由多个文件系统层(Filesystem Layers)组成的。每个层都是只读的,并且包含了文件和目录的变更。这种分层的文件系统结构使得镜像的构建和复用变得非常高效。每个层只需要存储差异部分,大大减小了镜像的体积。
  2. 只读性:Docker镜像是只读的,一旦创建就不能被修改。当需要修改一个镜像时,Docker会在原有的镜像上创建一个新的镜像,这个新镜像会包含原有镜像的所有层,并在其基础上添加新的层。
  3. 分层存储:Docker镜像的文件系统采用分层存储的方式。这意味着多个镜像可以共享同一个文件系统层,从而节省存储空间。当多个容器同时运行时,它们可以共享相同的基础镜像,只需在其基础上添加自己的可写层。
  4. 镜像的构建与复用:Docker镜像的构建是通过Dockerfile文件来定义的。Dockerfile中包含了一系列构建指令,用于描述如何从基础镜像中构建一个新的镜像。这种构建方式使得镜像的构建过程可自动化,并且易于复用和共享。

从操作系统原理角度来看,Docker镜像可以从操作系统原理角度来看,Docker镜像可以类比为操作系统中的文件系统快照。一个Docker镜像可以看作是一个只读的文件系统快照,它包含了应用程序运行所需的所有文件和目录。每个镜像层都相当于文件系统中的一个增量变更,它们按照层级的方式进行组织,使得镜像的构建和复用更加高效。

类似于操作系统中的进程,Docker容器是基于镜像创建的运行实体。当创建一个Docker容器时,Docker会在镜像的基础上添加一层可写的文件系统层,这个层称为容器层。容器层可以进行读写操作,而镜像层是只读的,这样就实现了镜像的复用和容器的隔离。

镜像相关命令

docker pull

# 用法
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

OPTIONS说明:

  • -a:拉取所有 tagged 镜像。
  • --disable-content-trust:忽略镜像的校验,默认开启。
  • -q: 可简化拉取过程中的日志输出。

除此之外,docker pull 也可通过镜像的 digest 进行拉取。语法格式为 docker pull <repository>@<digest>。

digest,是镜像内容的一个 Hash 值,即所谓的 Content Hash(内容散列)。只要镜像内容发生了变更,其内容散列值就一定会发生改变。注意,digest 是包含前面的 sha256 的,表示该 digest 的产生所采用的 Hash 算法是 SHA256。

docker images

# 用法
docker images [OPTIONS] [REPOSITORY[:TAG]]

OPTIONS说明:

  • -a:列出本地所有的镜像(含中间映像层,默认情况下,过滤掉中间映像层);

  • --digests:显示镜像的摘要信息;

  • -f:显示满足条件的镜像;

    使用reference作为筛选条件
    在使用reference时可以使用通配符 * 进行筛选。需要注意的是,reference只能筛选经过认证的镜像,未经过认证的镜像即使满足条件也不会被筛选。

    使用before作为筛选条件
    -f before 用于列举出本地镜像中指定镜像创建时间之前创建的所有镜像。

    使用since作为筛选条件
    -f since 用于列举出本地镜像中指定镜像创建时间之后的创建的所有镜像。

  • --format:指定返回值的模板文件;

    {{ }}里面的内容与Go语言的模板语法一样。

  • --no-trunc:显示完整的镜像信息;

    默认的 docker images 显示的镜像 id 是经过截取后的显示结果,仅显示了前 12 位。使用 --no-trunc 参数后显示的是完整的镜像 id。

  • -q:只显示镜像ID。

# 用法
docker search [OPTIONS] TERM

OPTIONS说明:

  • --limit:对结果进行数量限制;
  • --format:指定返回值的模板文件;
  • --no-trunc:显示完整的镜像描述;
  • -f <过滤条件>:列出收藏数大于指定值的镜像。

从 Docker Hub 查找所有镜像名包含 zookeeper,并且收藏数大于 10 的镜像。

参数说明:

  • NAME: 镜像仓库源的名称

  • DESCRIPTION: 镜像的描述

  • OFFICIAL: 是否 docker 官方发布

  • STARTS: 类似 Github 里面的 star,表示点赞、喜欢的意思。

  • AUTOMATED: 自动构建。

AUTOMATED 表示当前镜像是否是"自动化镜像"。什么是自动化镜像?就是使用 Docker Hub 连接一个包含 Dockerfile 文件(专门构建镜像用的文件)的 GitHub 仓库或 Bitbucket 仓库的源码托管平台,然后 Docker Hub 就会自动根据 Dockerfile 内容构建镜像。这种构建出的镜像会被标记为 AUTOMATED,这种构建镜像的方式称为 Trusted Build(受信构建)。只要 Dockerfile文件内容发生变化,那么 Docker Hub 就会构建出新的镜像。

docker rmi

基本使用

rmi,remove images。该命令用于删除指定的本地镜像。镜像通过:指定。如果省略要删除镜像的 tag,默认删除的是 lastest 版本。

删除多个镜像

docker rmi 命令可一次性删除多个镜像,多个要删除的镜像间使用空格分隔。

通过 ImageID 删除镜像

强制删除镜像

默认情况下,对于已经运行了容器的镜像是不能删除的,必须要先停止并删除了相关容器然后才能删除其对应的镜像。不过,也可以通过添加-f 选项进行强制删除。

删除所有镜像

使用组合命令删除所有镜像。当然,如果不携带-f 选项,则不会删除已打开容器的镜像。

dockerfile 复制代码
# 命令
[root@centos ~]#docker rmi -f $(docker images -q)

导出 / 导入镜像

导出镜像 save

docker save -o "导出的文件名" "多个镜像名,用空格分隔"

导入镜像 load

docker load 用于将一个 tar 文件导入并加载为一个或多个镜像。

docker load -i "要导入的tar文件"

镜像分层

当构建一个Docker镜像时,Docker会将镜像分解为多个文件系统层,每个层都是只读的,并且包含了文件和目录的变更。这种分层的文件系统结构使得镜像的构建和复用变得非常高效。

上面的示意图展示了一个由3个扩展镜像层和一个基础镜像层组成的Docker镜像。在基础镜像层之上的镜像层称为扩展镜像层。顾名思义,其是对基础镜像层功能的扩展。

在 Dockerfile 中,每条指令都是用于完成某项特定功能的,而每条指令都会生成一个扩展镜像层。

当创建一个新的Docker容器时,Docker会在只读层(扩展镜像层)的基础上添加一个可写层,这个可写层会包含容器运行时所需的文件和目录变更。这样,多个容器就可以共享同一个基础镜像层和多个只读层。分层存储的优势在于镜像的复用和共享。如果有多个镜像使用了相同的基础镜像层,它们可以共享这个基础层,只需在其基础上添加自己的可写层。这样就可以大大减小镜像的体积,并提高镜像的构建和复用效率。

在上面的示意图中,Docker镜像的分层存储通过联合文件系统来实现。可写层是容器运行时的一部分,用于存储容器运行时的变更和数据。只读层包含了基础镜像的内容,它们是只读的,并且可以被多个容器共享。

需要注意的是,这里的分层并不是物理上的分层,而是逻辑上的分层。在底层实现上,Docker使用了联合文件系统(UnionFS)来实现镜像的分层存储。联合文件系统是一种特殊的文件系统,它可以将多个不同的文件系统层合并为一个单一的文件系统。在Docker中,常用的联合文件系统有AUFS、OverlayFS和DeviceMapper等。

镜像摘要

Docker镜像摘要是镜像内容的唯一标识符,它是通过对镜像二进制数据进行哈希运算生成的。摘要可以确保所引用的映像在整个生命周期中始终是相同的。如果镜像内容发生改变,即使名字和标签相同,摘要也会发生改变。

在 docker pull 镜像结束后会给出该拉取的镜像的摘要 digest。并且通过 docker images --digests 命令也可以查看到镜像的摘要信息。

镜像摘要的作用

摘要的主要作用是区分相同<repository>:<tag>的不同镜像。

例如某个镜像在生产运行过程中发现存在一个 BUG。现对其进行了修复,并使用原标签将其 push 回了仓库,那么原镜像被覆盖。但生产环境中遗留了大量运行中的修复前镜像的容器。此时,通过镜像标签已经无法区分镜像是修复前的还是修复后的了,因为它们的标签是相同的。此时通过查看镜像的 digest 就可以区分出修改前后版本,因为内容发生了变化,digest 一定会变。为了确保再次拉取到的是修复后的镜像,可通过 digest 进行镜像拉取。其用法是:docker pull <repository>@<digest>

分发散列值

在 push 或 pull 镜像时,都会对镜像进行压缩以减少网络带宽和传输时长。但压缩会改变镜像内容,会导致经过网络传输后,镜像内容与其 digest 不相符。为了避免该问题,Docker 又为镜像配置了 Distribution Hash(分发散列值)。在镜像被压缩后立即计算分发散列值,然后使该值随压缩过的镜像一同进行发送。在接收方接收后,立即计算压缩镜像的分发散列值,再与携带的分发散列值对比。如果相同,则说明传输没有问题。

相关推荐
一勺菠萝丶13 分钟前
MongoDB 常用操作指南(Docker 环境下)
数据库·mongodb·docker
小_太_阳20 分钟前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
Mitch31128 分钟前
【漏洞复现】CVE-2015-3337 Arbitrary File Reading
elasticsearch·网络安全·docker·漏洞复现
智慧老师29 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
Mitch31133 分钟前
【漏洞复现】CVE-2015-5531 Arbitrary File Reading
web安全·elasticsearch·网络安全·docker·漏洞复现
搬码后生仔2 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱2 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
我自飞扬临天下2 小时前
Docker常用命令
docker
Lx3523 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas
小池先生3 小时前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端