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

时间:2014-05-19 10:15:27

标签: docker docker-container docker-image

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

所以最终我有一个我的PostgreSQL实例的图像和我的Web应用程序的图像,其中的更改一直保持不变。

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

29 个答案:

答案 0 :(得分:928)

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

您可以使用docker images查看所有图片,而使用docker ps可以看到正在运行的容器(并且您可以看到所有带有docker ps -a的容器。)

因此,正在运行的图像实例是一个容器。

答案 1 :(得分:501)

来自Automating Docker Deployments的文章:

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

有些注意事项:

  1. IMAGE ID是图像的真实标识符的前12个字符。您可以创建给定图像的许多标记,但它们的ID都是相同的(如上所述)。
  2. VIRTUAL SIZE 虚拟因为它会累加所有不同底层的大小。这意味着该列中所有值的总和可能远大于所有这些图像使用的磁盘空间。
  3. REPOSITORY列中的值来自-t命令的docker build标志,或来自docker tag现有图像。您可以使用对您有意义的命名法自由标记图像,但是知道docker会将标记用作docker pushdocker 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. 您可以拥有仅可通过其图片ID识别的无标记图像。这些将获得<none> TAG和REPOSITORY。很容易忘记它们。
  8. 有关图片的更多信息,请访问Docker docsglossary

    什么是容器?

    要使用编程隐喻,如果图像是类,则容器是类的实例 - 运行时对象。容器有望成为您使用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标志识别已启动的容器。
    4. 如何避免图像和容器堆积?

      我对Docker的早期挫折之一是看似不断增加的未标记图像和已停止的容器。在少数几个场景中,这种累积导致硬盘驱动器的速度变慢,从而减慢了我的笔记本电脑或停止了自动构建管道。在任何地方谈论&#34;容器&#34;!

      我们可以将docker rmi与最近的dangling=true查询相结合,删除所有未标记的图片:

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

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

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

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

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

答案 2 :(得分:105)

虽然将容器视为正在运行的图像是最简单的,但这并非完全准确。

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

答案 3 :(得分:94)

简单易懂。

图片 -

  

用于的文件系统和配置(只读)应用程序   创建容器。 More detail

容器 -

  

这些是Docker镜像的运行实例。容器运行实际   应用。容器包括应用程序及其所有应用程序   依赖。它与其他容器共享内核并运行为   主机操作系统上用户空间中的隔离进程。 More detail

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

Docker守护程序 -

  

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

Docker客户端 -

  

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

Docker商店 -

  

Store是Docker镜像的注册表。您可以   将注册表视为所有可用Docker镜像的目录。

来自this博客的图片胜过千言万语。

Enter image description here

(如需更深入的了解,请阅读this。)

要点:

  • 从Docker hub中拉图像或从Dockerfile中构建=&gt;提供Docker镜像(不可编辑)。
  • 运行图片(docker run image_name:tag_name)=&gt;提供正在运行的图像即容器(可编辑)

答案 4 :(得分:78)

也许解释整个工作流程可以提供帮助。

一切都以 Dockerfile 开头。 Dockerfile是Image的源代码。

创建Dockerfile后,您可以构建它以创建容器的图像。该图像只是“源代码”的“编译版本”,即Dockerfile。

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

接下来,您可以使用该图片来运行容器。在许多方面,正在运行的容器与虚拟机非常相似(但没有hypervisor)。

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

答案 5 :(得分:38)

工作流

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

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

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

docker image ls

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

docker ps

答案 6 :(得分:32)

我无法理解图像图层的概念,尽管在这里阅读了所有问题,然后最终偶然发现了excellent documentation from Docker(杜!)。

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

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

  • 图层:每个图层代表图片Dockerfile中的指令。

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

  

FROM ubuntu:15.04

     

COPY。 /应用

     

RUN make / app

     

CMD python /app/app.py

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

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

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

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

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

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

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

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

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

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

答案 7 :(得分:23)

Dockerfile &gt; (构建)&gt; 图片&gt; (运行)&gt; <强>容器

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

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

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

答案 8 :(得分:11)

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

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

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

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

虽然大多数人使用Linux基础作为可执行文件,但只要主机操作系统可以运行它,它就可以是任何其他二进制应用程序。 (见creating a simple base image using scratch)。无论Docker镜像中的二进制文件是操作系统还是仅仅是应用程序,对于OS主机而言,它只是另一个进程,由预设的操作系统边界控制的包含进程。

其他应用程序,如Docker,可以告诉主机操作系统在运行过程中应用于哪个边界包括LXClibvirtsystemd。 Docker曾经使用这些应用程序间接与Linux操作系统交互,但现在Docker使用自己的名为“libcontainer”的库直接与Linux交互。

所以容器只是在受限模式下运行的进程,类似于chroot以前的进程。

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

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

答案 9 :(得分:11)

简单地说,如果图片,那么容器是类的实例是运行时对象

答案 10 :(得分:11)

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

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

  1. 制作图片
  2. 启动容器
  3. 对容器进行更改
  4. 将容器保存为图像

答案 11 :(得分:5)

许多答案指出了这一点:您 build Dockerfile 以获取图像,而您 运行 图片以获取容器

但是,以下步骤帮助我更好地了解了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

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

答案 12 :(得分:3)

与编程方面一样,

图片是源代码。

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

Simillar到“当为图像创建实例时”,它被称为“容器

答案 13 :(得分:3)

Docker镜像打包应用程序运行所需的应用程序和环境,容器是图像的运行实例。

图像是docker的包装部分,类似于&#34;源代码&#34;或者一个&#34;程序&#34;。容器是docker的执行部分,类似于&#34; process&#34;。

在问题中,只有&#34;程序&#34;部分被引用并且是图像。 &#34;跑步&#34; docker的一部分是容器。当一个容器运行并进行更改时,就好像该过程对其自己的源代码进行了更改并将其另存为新图像。

答案 14 :(得分:3)

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

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

答案 15 :(得分:3)

我想在docker imagescontainers之间填写缺失的部分。 Docker 对容器使用 union文件系统 UFS ),该文件系统允许将多个文件系统安装在层次结构中并显示为单个文件系统。映像中的文件系统已作为read-only层挂载,对运行中的容器所做的任何更改都将对安装在此之上的read-write层进行。因此,Docker只需查看最顶层的读写层,即可找到对运行中的系统所做的更改。

答案 16 :(得分:2)

我认为最好在开始时解释一下。

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

它调用 Docker CLI ,它负责接收Docker命令并转换为调用 Docker服务器命令。 Docker服务器一获得运行图像的命令,它就会检查图像缓存是否保存图像的天气这样的名字。

假设hello-world不存在。 Docker服务器转到 Docker Hub (Docker Hub只是一个免费的图像存储库),问,嘿,Hub,您是否有一个名为的 image hello-world? 集线器响应-是的,我愿意。然后把它给我。然后下载过程开始。一旦下载了 Docker映像 Docker服务器便将其放入映像缓存

因此,在解释什么是Docker映像和Docker容器之前,我们先介绍一下计算机上的操作系统以及其运行软件的方式。

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

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

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

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

答案 17 :(得分:1)

正如对象是面向对象编程语言中类的实例一样,Docker 容器也是 Docker 镜像的实例。

答案 18 :(得分:1)

Docker 客户端、服务器、机器、图像、集线器、组合都是项目工具软件,这些软件组合在一起形成一个平台,其中围绕创建和运行称为容器的东西的生态系统,现在如果您运行命令 docker run redis 一个叫做 docker CLI 的东西联系到一个叫做 Docker Hub 的东西,它下载了一个叫做镜像的文件。 enter image description here

Docker 镜像:

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

这是一个存储在您的硬盘驱动器上的单个文件,您可以在某个时间使用此映像来创建称为容器的东西。 enter image description here

一个容器是一个镜像的实例,你可以把它想象成一个正在运行的程序,它有自己的独立硬件资源集,所以它有自己的小集或它自己的小内存空间有它的拥有自己的网络技术空间和自己的硬盘空间。

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

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

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

docker 服务器做的第一件事是检查它是否已经有一个本地副本,比如你个人机器上的 hello world 镜像或 hello world 文件的副本。所以 docker 服务器查看了一个叫做镜像的东西缓存。 enter image description here

现在因为你和我刚刚在我们的个人电脑上安装了 Docker,图像缓存目前是空的,我们之前没有下载过的图像。

因此,由于图像缓存是空的,Docker 服务器决定联系一个名为 Docker hub 的免费服务。 Docker Hub 是一个免费公共镜像的存储库,您可以免费下载并在您的个人计算机上运行。因此,Docker 服务器联系 Docker Hub 并下载 hello world 文件并将其存储在您的计算机上的图像缓存中,现在可以在未来的某个时刻快速重新运行,而无需从码头集线器。

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

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

enter image description here 容器是一个进程或一组进程,它们有一组专门分配给它的资源,在下面的图表中,无论何时我们考虑一个容器,我们都会有一些正在运行的进程向内核发送系统调用,内核将查看传入的系统调用并将其定向到硬盘驱动器的特定部分、RAM、CPU 或它可能需要的任何其他东西,并且这些资源中的每一个的一部分都可用于该单个过程。

答案 19 :(得分:1)

镜像是构建容器(运行实例)的蓝图。

答案 20 :(得分:1)

*在docker中,an image is an immutable file包含运行docker应用所需的源代码和信息。它可以独立于容器而存在。

* Docker容器为virtualized environments created during runtime,需要运行映像。 docker网站上有一幅图像显示了这种关系:

docs.docker.com image

答案 21 :(得分:1)

我会用以下类比来陈述它:

+-----------------------------+-------+-----------+
|             Domain          | Meta  | Concrete  |
+-----------------------------+-------+-----------+
| Docker                      | Image | Container |
| Object oriented programming | Class | Object    |
+-----------------------------+-------+-----------+

答案 22 :(得分:1)

图像容器的“快照”。您可以从容器中创建图像(新的“快照”),也可以从图像中创建新容器(实例化“快照”)。

例如,您可以从基本映像实例化一个新容器,在容器中运行一些命令,然后将其快照为新映像。然后,您可以从该新映像运行100个容器。

要考虑的其他事项:

  • 图像由图层组成,并且图层是快照“ diff”(因此,当您推送图像时,只需将“ diff”发送到注册表)。
  • Dockerfile在基本映像之上定义了一些命令,该命令创建了新层(“差异”),从而产生了新映像(“快照”)。
  • 图像标签不仅仅是标签。它们是图像的“全名”(“ repository:tag”)。如果同一张图片有多个名称,则在执行docker images时会显示多次。

答案 23 :(得分:1)

图像是一个类,作为对象的容器。

容器是图像的实例,因为对象是类的实例。

答案 24 :(得分:1)

Docker容器正在运行图像实例。您可以将图像与程序和容器相关联,并使用以下过程:)

答案 25 :(得分:1)

简而言之:

Container是内核中的一个分区(虚拟),它共享一个公共操作系统并运行一个映像(Docker镜像)。

容器是一个自我可持续的应用程序,它将包和所有必需的依赖项一起运行代码。

答案 26 :(得分:0)

  1. 图片 –它是容器的组成部分。它实际上是虚拟快照,但更轻巧。

  2. 容器 –这是一种虚拟化操作系统的方法,可以在资源隔离的进程中执行应用程序及其相关的依赖项。

虽然我们使用泊坞窗,但此刻我们获得了基本映像。然后,我们将其引导,进行相关更改并将这些更改保存在形成另一个映像的图层中。容器基本上是图像的一个实例。这意味着运行映像是一个容器。如果某人开始创建图像,则此刻他实际上正在运行一个容器。同一张图片上可能一次有多个正在运行的容器。

一个人可以使用以下代码查看所有图像:

码头工人图像

正在运行的容器可以通过以下方式查看:

docker ps

如果要查看所有容器,无论是否运行:

docker ps -a

答案 27 :(得分:0)

对于虚拟编程类比,您可以认为Docker有一个抽象的ImageFactory,它包含来自store的ImageFactories。

然后,一旦您想要从该ImageFactory创建一个应用程序,您将拥有一个新容器,您可以根据需要进行修改。 DotNetImageFactory将是不可变的,因为它充当抽象工厂类,它只提供你想要的实例。

IContainer newDotNetApp = ImageFactory.DotNetImageFactory.CreateNew(appOptions);
newDotNetApp.ChangeDescription("I am making changes on this instance");
newDotNetApp.Run();

答案 28 :(得分:0)

Dockerfile就像你的bash脚本一样产生tarball(Docker镜像)。

Docker容器就像tarball的解压缩版本一样。您可以在不同的文件夹(容器)中拥有任意数量的副本