Docker 镜像

简单介绍

容器镜像是一个只读包,它包含运行应用程序所需的一切。它包括应用程序代码、应用程序依赖项、一组最基本的操作系统结构和元数据。一个镜像可用于启动一个或多个容器。

如果你熟悉 VMware,就会认为映像与 VM 模板类似。虚拟机模板就像一个停止运行的虚拟机,而容器镜像就像一个停止运行的容器。如果你是一名开发人员,你可以把它们想象成类似于类。你可以从类中创建一个或多个对象,也可以从镜像中创建一个或多个容器。

我们从镜像注册表中提取容器镜像。最常见的注册表是 Docker Hub,但也有其他注册表。拉取操作会将镜像下载到本地 Docker 主机上,Docker 可以用它来启动一个或多个容器。

镜像由多个层组成,层层叠加,表现为一个对象。镜像内部是一个精简的操作系统(OS)以及运行应用程序所需的所有文件和依赖关系。由于容器的目的是快速和轻量级,因此镜像往往很小。

深入介绍

我们已经多次提到,镜像就像停止运行的容器。事实上,你可以停止一个容器并从中创建一个新的镜像。有鉴于此,镜像被认为是构建时的构造,而容器则是运行时的构造。

镜像和容器

上图显示了镜像与容器之间关系的高层视图。我们使用 docker run 和 docker service create 命令从一个镜像启动一个或多个容器。一旦从镜像启动了一个容器,这两个构造就会变得相互依赖,在使用镜像的最后一个容器停止并销毁之前,无法删除镜像。

镜像通常较小

容器的整个目的是运行单个应用程序或服务。这意味着它只需要运行应用程序的代码和依赖关系,而不需要其他任何东西。这意味着镜像也很小,并且去除了所有非必要部分。

例如 Alpine Linux 的官方镜像只有 7MB。这是因为它并不包含 6 种不同的外壳、3 种不同的软件包管理器等等......事实上,很多镜像都不包含外壳或软件包管理器--如果应用程序不需要,镜像中就不会包含。

镜像不包括内核。这是因为容器共享其运行主机的内核。镜像中包含的操作系统组件通常只有几个重要的文件系统组件和其他基本结构。这就是为什么有时你会听到有人说 "镜像包含足够多的操作系统"。

提取镜像

安装完毕的 Docker 主机在本地资源库中没有镜像。

Linux 主机上的本地镜像库通常位于 /var/lib/docker/<storage-driver>。如果你在 Mac 或 PC 上使用 Docker Desktop,一切都会在虚拟机中运行。

您可以使用以下命令检查 Docker 主机的本地存储库中是否有任何镜像。

docker images

将镜像放到 Docker 主机上的过程称为 "拉取"。因此,如果你想在 Docker 主机上安装最新的 Busybox 镜像,就必须拉取它。使用以下命令拉取一些镜像,然后检查它们的大小。

docker pull redis:latest
docker pull alpine:latest
docker images

正如你所看到的,这些镜像现在已经出现在 Docker 主机的本地存储库中。

镜像注册表

我们将镜像集中存储在称为注册中心的地方。大多数现代注册中心都实施了 OCI 规范,我们有时称其为 OCI 注册中心。注册中心的工作是安全地存储容器镜像,并使它们易于从不同环境中访问。有些注册中心提供高级服务,例如镜像扫描和与构建管道集成。

最常见的注册表是 Docker Hub,但也有其他注册表,包括第三方注册表和安全的内部注册表。不过,Docker 客户端默认使用 Docker Hub。

镜像注册中心包含一个或多个镜像存储库。反过来,镜像存储库也包含一个或多个镜像。这可能有点令人困惑,因此下图展示了一个包含 3 个存储库的镜像注册表,每个存储库都有一个或多个镜像。

官方仓库

Docker Hub是默认的镜像仓库,顾名思义,官方存储库是经过应用程序供应商和 Docker 公司审核和策划的镜像的家园。这意味着它们应包含最新的高质量代码,这些代码应安全、文档齐全并符合最佳实践。

如果一个版本库不是官方的,那么它可能就像荒野西部一样--你不应该认为它们是安全的、文档齐全的或根据最佳实践构建的。这并不是说它们所包含的镜像不好。非官方资源库中也有一些优秀的东西。只是在信任它们的代码之前,你需要非常小心。

大多数流行的应用程序和操作系统在 Docker Hub 上都有官方存储库。它们很容易发现,因为它们位于 Docker Hub 名称空间的顶层,并带有绿色的 "Docker 官方镜像 "徽章。

镜像命名和标记

处理来自官方软件仓库的镜像只需提供软件仓库名称和标签,并用冒号(:)分隔即可。在处理来自官方版本库的镜像时,docker pull 的格式是:

docker pull <repository>:<tag>

在前面的 Linux 示例中,我们使用以下两条命令调用了 Alpine 和 Redis 映像:

它们从顶层的 "alpine "和 "redis "存储库中提取标记为 "latest "的镜像。

下面的示例展示了如何从官方资源库中提取各种不同的镜像:

docker pull mongo:4.2.24
// 这将从官方的 `mongo` 代码库中提取标记为 `4.2.24` 的镜像。
docker pull busybox:glibc
// 这将从官方的 `busybox` 代码库中提取标记为 `glibc` 的图片。
关于这些命令,有几点需要说明。

首先,如果你没有在版本库名称后指定镜像标记,Docker 会认为你指的是标记为 latest 的镜像。如果版本库中没有标记为 latest 的镜像,命令就会失败。

其次,latest标签没有任何神奇的力量。镜像被标记为 latest 并不能保证它就是版本库中最新的镜像!

从非官方版本库中提取镜像的方法基本相同,只需在版本库名称前加上 Docker Hub 用户名或组织名称即可!下面的示例展示了如何从一个 Docker Hub 账户名为 nigelpoulton 的不可信任者拥有的 tu-demo 资源库中提取 v2 映像。

docker pull nigelpoulton/tu-demo:v2
// 这将从 `nigelpoulton` 命名空间内的 `tu-demo` 软件库中提取标记为 `v2` 的镜像。

如果想从第三方注册中心(不是 Docker Hub)提取镜像,只需在版本库名称前加上注册中心的 DNS 名称即可。例如,下面的命令会从 Google Container Registry (gcr.io) 上的 google-containers/git-sync repo 中提取 3.1.5 映像。

docker pull gcr.io/google-containers/git-sync:v3.1.5

请注意,从 Docker Hub 和其他注册中心拉取的体验是完全一样的。

带有多个标签的镜像

关于镜像标签的最后一句话......一个镜像可以拥有任意数量的标签。这是因为标签是作为元数据与镜像一起存储的任意字母数字值。

下面的示例输出中似乎显示了三个镜像。但仔细一看,其实是两个镜像--带有 c610c6a38555 ID 的图像被标记为latest和 v1。

这就是前面发出的关于最新标签的警告的一个完美例子。在这个例子中,latest标签指向的是与 v1 标签相同的镜像。这意味着它指向的是两个镜像中较早的一张!这个故事的寓意是,latest标签是一个任意标签,不能保证指向版本库中的最新镜像!

Docker image命令

Docker 提供了 --filter 标志,用于过滤 docker images 返回的镜像列表。

下面的示例只会返回悬挂镜像。

docker images --filter dangling=true

悬挂镜像是指不再标记的镜像,在列表中显示为 <无>:<无>。出现这种情况的一种常见方式是使用已经存在的标记构建新镜像。出现这种情况时,Docker 会在构建新镜像时注意到已有镜像拥有相同的标记,然后从已有镜像中移除标记,并将其赋予新镜像。

举例来说,基于 alpine:3.4 创建了一个新的应用程序镜像,并将其标记为 dodge:challenger。然后更新镜像,使用 alpine:3.5 代替 alpine:3.4。构建新图像时,该操作将创建一个标记为 dodge:challenger 的新镜像,并移除旧镜像上的标记。旧图像将成为悬挂镜像。

可以使用docker image prune 命令删除系统中所有悬挂的镜像。如果添加 -a 标志,Docker 还会删除所有未使用的镜像(未被任何容器使用的镜像)。

Docker 目前支持以下过滤器:
  • dangling: 接受 true 或 false,只返回有悬挂的镜像(true)或无悬挂的镜像(false)。
  • before:需要镜像名称或 ID 作为参数,并返回在其之前创建的所有镜像。
  • since: 同上,但返回在指定镜像之后创建的镜像。
  • label:标签: 根据是否存在标签或标签和值过滤镜像。docker images 命令不会在输出中显示标签。

对于所有其他过滤,您可以使用reference。

下面是一个例子,使用引用只显示标记为 "latest "的镜像

你还可以使用 --format 标志,使用 Go 模板对输出进行格式化。例如,以下命令只会返回 Docker 主机上镜像的大小属性。

docker images --format "{{.Size}}"

使用以下命令返回所有镜像,但只显示 repo、标签和大小。

docker images --format "{{.Repository}}: {{.Tag}}: {{.Size}}"

如果需要更强大的过滤功能,可以使用操作系统和 shell 提供的工具,如 grep 和 awk

以上步骤,并没有解释每个docker命令的含义,是比较基础的操作,如果您对以上的命令不太熟悉,可以参考我的docekr课程,有对各类命令的详细讲解:Docker 实战_在线视频教程-CSDN程序员研修院

相关推荐
Shepherd06191 小时前
【Jenkins实战】Windows安装服务启动失败
运维·jenkins
Biomamba生信基地2 小时前
Linux也有百度云喔~
linux·运维·服务器·百度云
new_abc2 小时前
Ubuntu 22.04 ftp搭建
linux·运维·ubuntu
Algorithm15762 小时前
mac上使用docker搭建gitlab
macos·docker·gitlab
鹿鸣天涯3 小时前
‌华为交换机在Spine-Leaf架构中的使用场景
运维·服务器·网络
小白也有IT梦3 小时前
域名绑定服务器小白教程
运维·nginx
有梦想的咕噜3 小时前
Secure Shell(SSH) 是一种网络协议
运维·网络协议·ssh
dntktop3 小时前
免费,WPS Office教育考试专用版
运维
苹果醋33 小时前
C语言 strlen 函数 - C语言零基础入门教程
java·运维·spring boot·mysql·nginx
loong_XL4 小时前
automa 浏览器自动化工具插件
运维·自动化