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

bib*_*tha 804 docker docker-image docker-container

使用Docker时,我们从基本映像开始.我们启动它,创建更改并将这些更改保存在层中,形成另一个图像.

所以我最终得到了一个用于我的PostgreSQL实例的图像和一个用于我的Web应用程序的图像,这些图像继续保持不变.

所以问题是:什么是容器?

Tho*_*rig 1093

图像的实例称为容器.你有一个图像,这是你描述的一组图层.如果您启动此图像,则您拥有此图像的运行容器.您可以拥有许多相同图像的运行容器.

您可以看到所有图像,docker images而您可以看到正在运行的容器docker ps(并且您可以看到所有容器docker ps -a).

因此,图像的运行实例是容器.

  • 图像是食谱,容器是蛋糕;-)你可以用给定的食谱制作任意数量的蛋糕 (280认同)
  • @VictorDombrovsky一个停止的容器是冰箱里的蛋糕. (105认同)
  • 那么,图像和停止的容器有什么区别? (87认同)
  • @JohnnyWiller类比有其限制,但也许我们可以看到Dockerfile是你的成分购物清单;-).否则调用Dockerfile的配方,图像模具,容器仍然是美味的蛋糕 (47认同)
  • @Julien如果图像是配方,那么Doc​​kerfile呢?:) (29认同)
  • 我喜欢@x-yuri 的类比。Dockerfile是源代码,镜像是可执行文件,容器是进程 (5认同)
  • 诸如程序和流程之类的东西? (2认同)
  • 它类似于oop中的类-对象关系。其中图像是房屋的蓝图,而根据该蓝图建造的所有房屋(图像)称为容器。 (2认同)
  • recipe-cake,class-object:这意味着每个容器都有图像层的副本吗?如果图像有Ubuntu 14.04 + MongoDB,那么每个容器中都会有这些副本吗?看起来像我的VM.困惑. (2认同)
  • @VictorDombrovsky,停止的容器仍然是容器(它不会成为图像;)) (2认同)
  • 对我来说,理解和解释图像和容器之间关系的术语是图像是模板,容器是这些模板的实例。 (2认同)

pai*_*lee 549

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

Docker镜像与容器

在Dockerland,有图像容器.这两者密切相关,但截然不同.对我来说,抓住这种二分法已经极大地澄清了Docker.

什么是图像?

图像是一个惰性的,不可变的文件,它本质上是容器的快照.使用build命令创建映像,并且在使用run启动时它们将生成容器.映像存储在Docker注册表中,例如registry.hub.docker.com.因为它们可能变得非常大,所以图像被设计成由其他图像层组成,允许在通过网络传输图像时发送大量数据.

可以通过运行列出本地图像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
Run Code Online (Sandbox Code Playgroud)

有些事情需要注意:

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

有关图像的更多信息可从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
Run Code Online (Sandbox Code Playgroud)

在这里,我正在运行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`
Run Code Online (Sandbox Code Playgroud)

这些是Docker的已知痛点,可能会在将来的版本中解决.但是,通过对图像和容器的清晰理解,可以通过以下几种方法避免这些情况:

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

  • 良好的差异化bte图像和容器.为像我这样的初学者提供了很多帮助. (4认同)
  • 在较新版本的docker中,您可以使用`docker image prune`来清理悬空图像.[修剪未使用的Docker对象](https://docs.docker.com/config/pruning/) (3认同)
  • 我只是用docker system prune来清理一切 (3认同)
  • 我想我坚持的是图像如何运行(我在Windows上使用boot2docker)。为什么我们要为应用程序创建映像,例如mysql?此时,mysql甚至如何运行?我不需要Linux映像才能在上面运行mysql吗? (2认同)

Adr*_*uat 119

虽然这是最简单的认为容器作为一个正在运行的形象,这是不是准确.

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

  • @JanusTroelsen使用`docker create`. (12认同)
  • 好的,做了一些阅读并在这个帖子中得到了答案."当删除容器时,也会删除可写层.底层图像保持不变." (3认同)
  • 如何在不运行图像的情况下将图像转换为容器? (2认同)
  • 这有点令人困惑。我们说图像是不可变的,但是当作为容器运行时,它会像您所说的那样存储对可变顶层的任何更改。但是当停止时,这些更改是否会保存为图像中的这个新图层?如果是,那么原始图像怎么可能是不可变的? (2认同)

Imr*_*ran 112

用简单的话说.

图片 -

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

容器 -

这些是Docker镜像的运行实例.容器运行实际的应用程序.容器包括应用程序及其所有依赖项.它与其他容器共享内核,并作为主机操作系统上用户空间中的独立进程运行.更多细节.


其他需要注意的重要条款:


Docker守护程序 -

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

Docker客户端 -

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

Docker商店 -

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

一张图片胜过千言万语.

在此输入图像描述

(为了更深入的了解,请阅读此内容.)

摘要:

  • 图像从泊坞毂从或建立一个Dockerfile =>给出一个泊坞图像(不可编辑).
  • 运行图像(docker run image_name:tag_name)=>给出一个正在运行的图像即容器(可编辑)


Tk4*_*421 86

也许解释整个工作流程可以帮助.

一切都从Dockerfile开始.Dockerfile是Image的源代码.

创建Dockerfile后,您可以构建它以创建容器的映像.图像只是"源代码"的"编译版本",即Dockerfile.

获得容器的映像后,应使用注册表重新分发容器.注册表就像一个git存储库 - 你可以推送和拉取图像.

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

这篇文章解释了很多关于docker容器的基本知识(它讲的是Docker和Puppet,但是有很多概念可以在任何上下文中使用)


Sri*_*bat 42

工作流程

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

+------------+  docker build   +--------------+  docker run -dt   +-----------+  docker exec -it   +------+
| Dockerfile | --------------> |    Image     | --------------->  | Container | -----------------> | Bash |
+------------+                 +--------------+                   +-----------+                    +------+
                                 ^
                                 | docker pull
                                 |
                               +--------------+
                               |   Registry   |
                               +--------------+
Run Code Online (Sandbox Code Playgroud)

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

docker image ls
Run Code Online (Sandbox Code Playgroud)

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

docker ps
Run Code Online (Sandbox Code Playgroud)

  • 但 ASCII 艺术中所需的滚动是一个问题。 (2认同)

Hop*_*ing 39

尽管在这里阅读了所有问题,我仍无法理解图像图层的概念,然后最终偶然发现了Docker的这些优秀文档(呃!).

这个例子确实是理解整个概念的关键.这是一个冗长的帖子,所以我总结了需要真正掌握以获得清晰度的关键点.

  • 图像:Docker镜像是由一系列只读层构建的

  • 图层:每个图层代表图像Dockerfile中的一条指令.

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

来自ubuntu:15.04

复制./应用

运行make/app

CMD python /app/app.py

重要的是,每个图层只是与之前图层的一组差异.

  • 容器.创建新容器时,在基础图层的顶部添加新的可写层.该层通常称为"容器层".如写入新文件,修改现有的文件,并删除文件到正在运行的容器进行的所有变化,都被写入该写容器层.

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

从磁盘大小的角度理解图像cnd容器

要查看正在运行的容器的大致大小,可以使用该docker ps -s命令.你得到sizevirtual size两个输出的:

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

  • 虚拟大小:容器使用的只读图像数据所使用的数据量.多个容器可以共享一些或所有只读图像数据.因此,这些不是附加的.即,您无法添加所有虚拟大小来计算图像使用的磁盘大小

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

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

我希望能帮助别人喜欢我.

  • 感谢您的评论,它确认了大小和虚拟大小之间的差异,并且对于多个容器共享相同的只读数据非常有趣,并且这是获得操作系统磁盘空间。 (2认同)

Mah*_*alt 28

Dockerfile >(构建)> 图像 >(运行)> 容器.

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

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

  • 容器:虚拟操作系统本身,你可以ssh到它并运行你想要的任何命令,就好像它是一个真实的环境.您可以从同一个Image运行1000多个容器.

  • 非常好的比喻。如果我能给你1000个赞的话我会的。 (3认同)

kog*_*oia 16

简单地说,如果一个图像是一个,那么一个容器是一个类的实例就是一个运行时对象.


kwe*_*360 12

docker的核心概念是使创建"机器"变得容易,在这种情况下可以将其视为容器.容器有助于重用,允许您轻松创建和删除容器.

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

  1. 创建一个图像
  2. 开始一个容器
  3. 对容器进行更改
  4. 将容器保存为图像


小智 12

容器只是一个可执行的二进制文件,由主机操作系统在一组限制下运行,这些限制是使用知道如何告诉操作系统应用哪些限制的应用程序(例如,docker)预设的.

典型的限制是与进程隔离相关,与安全相关(如使用SELinux保护)和与系统资源相关(内存,磁盘,CPU,网络).

直到最近,只有基于Unix的系统中的内核才支持在严格限制下运行可执行文件的能力.这就是今天大多数容器谈话主要涉及Linux或其他Unix发行版的原因.

Docker是那些知道如何告诉操作系统(主要是Linux)运行可执行文件的限制的应用程序之一.可执行文件包含在Docker镜像中,它只是一个tarfile.该可执行文件通常是预先配置为在其中运行一个或多个应用程序的Linux发行版(Ubuntu,centos,Debian等)的精简版本.

虽然大多数人使用Linux基础作为可执行文件,但只要主机操作系统可以运行它,它就可以是任何其他二进制应用程序.(请参阅使用临时创建简单的基本图像).无论Docker镜像中的二进制文件是操作系统还是仅仅是应用程序,对于OS主机而言,它只是另一个进程,由预设的操作系统边界控制的包含进程.

其他应用程序,如Docker,可以告诉主机操作系统在运行时应用于哪个边界包括LXC,libvirtsystemd.Docker曾经使用这些应用程序间接地与Linux OS交互,但现在Docker使用自己的名为" libcontainer " 的库直接与Linux交互.

所以容器只是在限制模式下运行的进程,类似于chroot过去做的事情.

IMO将Docker与其他任何容器技术区别开来的是它的存储库(Docker Hub)及其管理工具,这使得使用容器非常容易.

请参阅 https://en.m.wikipedia.org/wiki/Docker_(Linux_container_engine)


Roh*_*cha 6

图像等效于OOP中的类定义,并且图层是该类的不同方法和属性。

容器是图像的实际实例,就像对象是实例的实例还是类的实例一样。


Aka*_*all 6

正如许多答案指出的那样:构建 Dockerfile来获取映像,然后运行 image来获取容器

但是,以下步骤有助于我更好地了解什么是Docker映像和容器:

1)构建Dockerfile:

docker build -t my_image dir_with_dockerfile

2)将图像保存到.tar文件

docker save -o my_file.tar my_image_id

my_file.tar将存储图像。使用打开它tar -xvf my_file.tar,您将看到所有图层。如果您更深入地研究每一层,则可以看到在每一层中添加了哪些更改。(它们应该非常接近Dockerfile中的命令)。

3)要查看容器内部,您可以执行以下操作:

sudo docker run -it my_image bash

您会发现它非常像一个操作系统。


tot*_*rio 6

图像视为容器的“快照”可能会有所帮助。

您可以从容器制作图像(新的“快照”),也可以从图像开始新的容器(实例化“快照”)。例如,您可以从基础映像实例化一个新容器,在容器中运行一些命令,然后将其“快照”为新映像。然后,您可以从该新映像实例化 100 个容器。

其他需要考虑的事项:

  • 图像由层组成,层是快照“差异”;当您推送图像时,只有“差异”会发送到注册表。
  • Dockerfile定义了一个基本图像的顶部某些命令,创建新的层(“diff文件”),其结果在新的图像(“快照”)。
  • 容器总是从图像实例化。
  • 图片标签不仅仅是标签。它们是图像的“全名”(“repository:tag”)。如果同一个图像有多个名称,则在执行docker images.


Lor*_*ord 6

Docker Client、Server、Machine、Images、Hub、Compose 都是项目、工具、软件,它们组合在一起形成一个平台,其中围绕创建和运行称为容器的东西的生态系统,现在如果您运行命令docker run redis称为 docker CLI 的东西就达到了到一个叫做 Docker Hub 的东西,它下载了一个叫做镜像的文件。 在此输入图像描述

Docker 镜像:

映像是一个包含所有依赖项以及运行特定程序所需的所有配置的单个文件,例如redis是您刚刚下载的映像(通过运行命令docker run redis)应该运行。

这是存储在硬盘驱动器上的单个文件,在某些时候您可以使用此映像来创建称为容器的东西。 在此输入图像描述

容器是图像的一个实例,您可以将其视为一个正在运行的程序,拥有自己独立的一组硬件资源,因此它有自己的一小部分,或者它自己的小内存空间有自己的小空间网络技术和自己的硬盘空间也很小。

现在让我们检查一下您何时发出以下命令: sudo docker run hello-world

上面的命令将启动 docker 客户端或 docker CLI,Docker CLI 负责从你那里获取命令,对它们进行一些处理,然后将命令传递给称为 docker 服务器的东西,而 docker 服务器位于当我们运行命令 Docker run hello-world 时,负责繁重的工作, 在此输入图像描述 这意味着我们想要使用名为 hello world 的图像启动一个新容器,hello world 图像内部有一个小标题程序,其唯一目的或唯一工作是打印出您在终端。

现在,当我们运行该命令并将其发送到 docker 服务器时,后台很快就会发生一系列操作。Docker 服务器发现我们正在尝试使用名为 hello world 的映像启动一个新容器。

docker 服务器做的第一件事是检查它是否已经有一个本地副本,例如您的个人计算机上的 hello world 图像或 hello world 文件的副本。因此,docker 服务器查看了称为图像缓存的东西。 在此输入图像描述

现在,因为你和我刚刚在我们的个人计算机上安装了 Docker,所以镜像缓存当前为空,我们没有之前已经下载过的镜像。

因此,由于图像缓存为空,docker 服务器决定使用名为 Docker hub 的免费服务。Docker Hub 是一个免费公共镜像存储库,您可以免费下载并在个人计算机上运行。因此,Docker 服务器连接到 Docker Hub,下载了 hello world 文件,并将其存储在您的计算机上的图像缓存中,现在可以在未来的某个时间非常快速地重新运行,而无需从以下位置重新下载它:码头工人中心。

之后docker服务器将使用它创建一个容器的实例,我们知道容器是一个镜像的实例,它的唯一目的是运行一个非常特定的程序。因此,docker 服务器实际上从图像缓存中获取该图像文件并将其加载到内存中,以从中创建一个容器,然后在其中运行一个程序。该单个程序的目的是打印出您看到的消息。

什么是容器: 首先,镜像是如何创建容器的蓝图。

在此输入图像描述 容器是一个进程或一组进程,它们有一组专门分配给它的资源,下图显示,每当我们考虑容器时,我们都会有一些正在运行的进程,这些进程向内核发送系统调用,内核将查看传入的系统调用并将其定向到硬盘驱动器、RAM、CPU 或它可能需要的任何其他部分的非常特定的部分,并且每个资源的一部分可供该单一资源使用过程。


小智 5

一个Docker镜像打包了应用运行所需的应用和环境,一个容器就是镜像的一个运行实例。

镜像是 Docker 的打包部分,类似于“源代码”或“程序”。容器是 Docker 的执行部分,类似于一个“进程”。

在这个问题中,只提到了“程序”部分,这就是图像。Docker 的“运行”部分是容器。当容器运行并进行更改时,就好像该进程在自己的源代码中进行了更改并将其保存为新映像。


Nan*_*mar 5

就像在编程方面一样,

图片为源代码。

源代码被编译和构建时,它被称为应用程序。

类似于“当为镜像创建实例时”,它被称为“容器”。

  • Dockerfile 就像源代码。图像就像源代码编译/构建后的可执行文件。容器就像从可执行文件运行的应用程序。 (5认同)

Ale*_*ili 5

我认为最好在开始时进行解释。

假设您运行命令docker run hello-world。发生什么了?

它调用Docker CLI,它负责接收 Docker 命令并转换为调用Docker 服务器命令。一旦Docker 服务器收到运行图像的命令,它就会检查图像缓存是否保存了具有此类名称的图像

假设 hello-world 不存在。Docker 服务器转到Docker Hub(Docker Hub 只是一个免费的图像存储库)并询问,嘿 Hub,你有一个名为的图像hello-world吗?集线器响应 - 是的,我愿意。那请给我吧。下载过程开始。一旦泊坞窗图像被下载,在泊坞服务器把它的图像缓存

所以在我们解释什么是 Docker 镜像和 Docker 容器之前,让我们先介绍一下您计算机上的操作系统以及它如何运行软件。

例如,当您在计算机上运行 Chrome 时,它​​会调用操作系统,操作系统本身会调用内核并询问,嘿,我想运行这个程序。内核设法从您的硬盘运行文件。

现在假设您有两个程序,Chrome 和 Node.js。Chrome 需要 Python 版本 2 才能运行,Node.js 需要 Python 版本 3 才能运行。如果您只在计算机上安装了 Python v2,则只会运行 Chrome。

为了使这两种情况都能正常工作,您需要以某种方式使用称为命名空间的操作系统功能。命名空间是一种功能,它使您有机会隔离进程、硬盘驱动器、网络、用户、主机名等。

因此,当我们谈论图像时,我们实际上谈论的是文件系统快照。的图像是包含方向和元数据,以建立一个特定的物理文件容器。的容器本身是一个实例图像; 它使用命名空间隔离硬盘驱动器,该命名空间仅适用于此容器。因此,容器是一个进程或一组进程,它对分配给它的不同资源进行分组。


moh*_*eem 5

我想填补docker images和之间的缺失部分containersDocker为容器使用联合文件系统( UFS ),它允许多个文件系统以层次结构安装并显示为单个文件系统。镜像中的文件系统已被挂载为一个read-only层,对正在运行的容器进行的任何更改都会对read-write挂载在该层之上的层进行。正因为如此,Docker 只需要查看最顶层的读写层就可以找到对正在运行的系统所做的更改。


Ale*_*ph0 5

我用下面的类比来表述:

+-----------------------------+-------+-----------+
|             Domain          | Meta  | Concrete  |
+-----------------------------+-------+-----------+
| Docker                      | Image | Container |
| Object oriented programming | Class | Object    |
+-----------------------------+-------+-----------+
Run Code Online (Sandbox Code Playgroud)