Docker 映像和容器之间有什么区别?

在使用 Docker 时,我们从基础映像开始。我们启动它,创建更改,然后将这些更改保存在形成另一个映像的层中。

因此,最终我为自己的 PostgreSQL 实例提供了一个映像,为我的 Web 应用程序提供了一个映像,对这些更改的更改将继续保留。

什么是容器?

答案

图像的实例称为容器。您有一张图像,它是您描述的一组图层。如果启动此映像,则该映像具有正在运行的容器。您可以有多个运行相同图像的容器。

您可以看到带有docker images所有映像,而可以看到带有docker ps正在运行的容器(也可以看到带有docker ps -a所有容器)。

因此,映像的运行实例是一个容器。

从我有关自动化 Docker 部署的文章中:

Docker 映像与容器

在 Dockerland 中,有图像容器 。两者密切相关,但又截然不同。对我而言,掌握这种二分法极大地阐明了 Docker。

什么是图片?

图像是一种惰性的,不可变的文件,本质上是容器的快照。图像是使用build命令创建的,并且在运行 run时它们将产生一个容器。图像存储在 Docker 注册表中,例如Registry.hub.docker.com 。由于图像可能会变得很大,因此图像被设计为由其他图像层组成,从而在通过网络传输图像时允许发送最少量的数据。

可以通过运行docker images列出本地docker images

REPOSITORY                TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                    13.10               5e019ab7bf6d        2 months ago        180 MB
ubuntu                    14.04               99ec81b80c55        2 months ago        266 MB
ubuntu                    latest              99ec81b80c55        2 months ago        266 MB
ubuntu                    trusty              99ec81b80c55        2 months ago        266 MB
<none>                    <none>              4ab0d9120985        3 months ago        486.5 MB

注意事项:

  1. IMAGE ID 是图像的真实标识符的前 12 个字符。您可以为给定图像创建许多标签,但它们的 ID 都相同(如上所述)。
  2. 虚拟大小是虚拟的,因为它累加了所有不同底层的大小。这意味着该列中所有值的总和可能比所有这些映像使用的磁盘空间大得多。
  3. REPOSITORY 列中的值来自docker build命令的-t标志,或者来自docker tag现有映像。您可以使用对您有意义的命名法来随意标记图像,但是您知道 docker 将在docker pushdocker pull中将标记用作注册表位置。
  4. 标记的完整格式为[REGISTRYHOST/][USERNAME/]NAME[:TAG] 。对于上述ubuntu ,推断 REGISTRYHOST 为registry.hub.docker.com 。因此,如果计划在docker.example.com的注册表中存储名为my-application docker.example.com ,则应标记该映像docker.example.com/my-application
  5. TAG 列只是完整标签的 [:TAG] 部分。这是不幸的术语。
  6. latest标签不是神奇的标签,它只是未指定标签时的默认标签。
  7. 您可以具有只能通过其图像 ID 识别的未标记图像。这些将获得<none>标记和存储库。忘记它们很容易。

有关映像的更多信息,请参阅Docker 文档词汇表

什么是容器?

要使用编程隐喻,如果图像是类,则容器是类的实例 - 运行时对象。容器是希望使用 Docker 的原因。它们是在其中运行应用程序的环境的轻巧且可移植的封装。

使用docker ps查看本地正在运行的容器:

CONTAINER ID        IMAGE                               COMMAND                CREATED             STATUS              PORTS                    NAMES
f2ff1af05450        samalba/docker-registry:latest      /bin/sh -c 'exec doc   4 months ago        Up 12 weeks         0.0.0.0:5000->5000/tcp   docker-registry

在这里,我正在运行 docker 注册表的 dockerized 版本,以便我有一个私人位置来存储我的图像。同样,需要注意一些事项:

  1. 与 IMAGE ID 相似,CONTAINER ID 是容器的真实标识符。它具有相同的形式,但是它标识不同种类的对象。
  2. docker ps仅输出正在运行的容器。您可以使用docker ps -a查看所有容器( 正在运行或已停止 )。
  3. NAMES 可通过--name标志用于标识已启动的容器。

如何避免图像和容器堆积

我对 Docker 的早期挫败之一是看似无休止的无标记映像和停止容器的不断积累 。在少数情况下,这种堆积会导致硬盘驱动器用尽,从而减慢我的笔记本电脑速度或中止自动构建流程。谈论 “无处不在的容器”!

我们可以通过结合docker rmi和最近的dangling=true查询来删除所有未标记的图像:

docker images -q --filter "dangling=true" | xargs docker rmi

Docker 无法删除现有容器后面的映像,因此您可能必须首先使用docker rm删除已停止的容器:

docker rm `docker ps --no-trunc -aq`

这些是 Docker 的已知痛点 ,可能会在将来的版本中解决。但是,只要对图像和容器有清楚的了解,可以通过以下两种方法避免这些情况:

  1. 始终使用docker rm [CONTAINER_ID]删除无用的,停止的容器。
  2. 始终使用docker rmi [IMAGE_ID]删除无用的,停止的容器后面的图像。

虽然将容器视为运行中的映像是最简单的,但这并不是准确。

图像实际上是可以转换为容器的模板。为了将映像转换为容器,Docker 引擎会获取映像,在顶部添加一个读写文件系统,并初始化各种设置,包括网络端口,容器名称,ID 和资源限制。正在运行的容器具有当前正在执行的进程,但是也可以停止容器(或在 Docker 的术语中退出容器)。一个退出容器是一样的图像,因为它可以重新启动,将保留其设置和文件系统的任何变化。

简单来说。

图片 -

用于创建容器的文件系统和配置(只读)应用程序。 更多细节

容器 -

这些正在运行的 Docker 映像实例。容器运行实际的应用程序。容器包含一个应用程序及其所有依赖项。它与其他容器共享内核,并在主机 OS 上的用户空间中作为隔离进程运行。 更多细节


其他重要注意事项:


Docker 守护进程 -

在管理构建,运行和分发 Docker 容器的主机上运行的后台服务。

Docker 客户端 -

允许用户与 Docker 守护程序进行交互的命令行工具。

Docker 商店 -

除其他事项外,Store 是 Docker 映像的注册表。您可以将注册表视为所有可用 Docker 映像的目录。

这篇博客文章的图片值得一千个单词。

在此处输入图片说明

(如需进一步了解,请阅读此内容 。)

摘要:

  • 从 Docker 集线器拉映像或从 Dockerfile 构建 => 提供 Docker 映像(不可编辑)。
  • 运行映像( docker run image_name:tag_name )=> 提供运行映像,即容器(可编辑)

也许解释整个工作流程会有所帮助。

一切都始于Dockerfile 。 Dockerfile 是映像的源代码。

创建 Dockerfile 后,您将对其进行构建以创建容器的映像 。该图像只是 “源代码”(即 Dockerfile)的 “编译版本”。

有了容器的映像后,应使用注册表重新分配它。注册表就像一个 Git 存储库 - 您可以推送和拉取图像。

接下来,您可以使用该图像运行container 。在许多方面,一个正在运行的容器与虚拟机非常相似(但没有虚拟机管理程序 )。

工作流程

这是端到端的工作流程,显示了各种命令及其相关的输入和输出。那应该阐明图像和容器之间的关系。

+------------+  docker build   +--------------+  docker run -dt   +-----------+  docker exec -it   +------+
| Dockerfile | --------------> |    Image     | --------------->  | Container | -----------------> | Bash |
+------------+                 +--------------+                   +-----------+                    +------+
                                 ^
                                 | docker pull
                                 |
                               +--------------+
                               |   Registry   |
                               +--------------+

要列出您可以运行的图像,请执行:

docker image ls

要列出容器,您可以在以下位置执行命令:

docker ps

尽管阅读了这里的所有问题,但我还是不理解图像的概念,然后最终偶然发现了Docker 的出色文档documentation !)。

这个例子确实是理解整个概念的关键。这是一篇冗长的文章,因此我在总结一些要清楚地理解的关键点。

  • 图像 :Docker 图像由一系列只读层构建而成

  • :每层代表映像的 Dockerfile 中的一条指令。

Example :下面的 Dockerfile 包含四个命令,每个命令创建一个图层。

来自 ubuntu:15.04

复制。 / app

运行 make / app

CMD python /app/app.py

重要的是 ,每一层只是与它之前的一层的一组差异。

  • 货柜 。创建新容器时, 可以在基础层之上添加新的可写层 。该层通常称为 “容器层”。对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此可写容器层。

因此,容器和图像之间的主要区别是可写顶层 。在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。删除容器后,可写层也会被删除。基础图像保持不变。

从磁盘大小的角度了解映像 cnd 容器

要查看正在运行的容器的大致大小,可以使用docker ps -s命令。您将获得sizevirtual size作为以下两个输出:

  • 大小:用于每个容器的可写层的数据量(磁盘上)

  • 虚拟大小:用于容器使用的只读图像数据的数据量。多个容器可以共享部分或全部只读图像数据。 因此,这些不是累加的。也就是说,您无法添加所有虚拟大小来计算映像使用了多少磁盘空间

另一个重要概念是写时复制策略

如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件。另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。

希望对我这样的人有帮助。

Dockerfile →(构建)→ 映像 →(运行)→ 容器

  • Dockerfile :包含一组 Docker 指令,它们以您喜欢的方式配置您的操作系统,并安装 / 配置所有软件。

  • 图片 :已编译的 Dockerfile。每次需要运行容器时,都可以节省重建 Dockerfile 的时间。这是一种隐藏您的供应代码的方法。

  • 容器 :虚拟操作系统本身。您可以使用 ssh 并运行所需的任何命令,就像它是一个真实的环境一样。您可以从同一映像运行 1000 多个容器。

简而言之,如果图像 ,则容器是类的实例,是运行时对象

Docker 的核心概念是简化创建 “机器” 的过程,在这种情况下可以将其视为容器。容器有助于重用性,使您可以轻松地创建和删除容器。

图像描绘了每个时间点的容器状态。所以基本的工作流程是:

  1. 创建图像
  2. 启动一个容器
  3. 对容器进行更改
  4. 将容器另存为图像