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

问题描述 投票:668回答:21

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

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

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

docker docker-container docker-image
21个回答
981
投票

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

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

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


12
投票

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

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

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

12
投票

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


6
投票

许多答案指出了这一点:您构建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

你可以看到它非常像操作系统。


3
投票

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

图像是docker的包装部分,类似于“源代码”或“程序”。容器是docker的执行部分,类似于“进程”。

在这个问题中,只有“程序”部分被引用,那就是图像。 docker的“运行”部分是容器。当一个容器运行并进行更改时,就好像该进程对其自己的源代码进行了更改并将其另存为新映像。


3
投票

在编程方面,

图像是源代码。

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

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


3
投票

Image与OOP中的类定义等效,层是该类的不同方法和属性。

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


1
投票

简而言之:

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

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


1
投票

Docker容器正在运行映像的实例。您可以将图像与程序和带有进程的容器相关联:)


1
投票

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

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


0
投票

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

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


516
投票

从我关于Automating Docker Deployments的文章:

Docker镜像与容器

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

What's an Image?

图像是一个惰性的,不可变的文件,它本质上是容器的快照。使用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. 您可以使用仅可通过其IMAGE ID识别的未标记图像。这些将获得<none> TAG和REPOSITORY。很容易忘记它们。

有关图像的更多信息,请访问Docker docsglossary

What's a container?

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

How to avoid image and container buildup?

我对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的known pain points,可能会在将来的版本中解决。但是,通过对图像和容器的清晰理解,可以通过以下几种方法避免这些情况:

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

0
投票

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

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

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

111
投票

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

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


104
投票

用简单的话说。

图片 -

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

容器 -

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


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


Docker守护程序 -

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

Docker客户端 -

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

Docker商店 -

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

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

Enter image description here

(有关更深入的理解,请阅读this。)

摘要:

  • 从Docker hub中提取图像或从Dockerfile中构建=>提供Docker镜像(不可编辑)。
  • 运行图像(docker run image_name:tag_name)=>给出一个正在运行的图像即容器(可编辑)

78
投票

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

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

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

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

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

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


41
投票

Workflow

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

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

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

docker image ls

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

docker ps

34
投票

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

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

  • 图像:Docker镜像是由一系列只读层构建的
  • 图层:每个图层代表图像Dockerfile中的指令。

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

来自ubuntu:15.04

复制。 /应用

运行make / app

CMD python /app/app.py

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

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

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

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

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

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

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

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

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


25
投票

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

  • Dockerfile:包含一组docker指令,以您喜欢的方式配置您的操作系统,并安装/配置您的所有软件。
  • 图片:已编译的Dockerfile。每次需要运行容器时,可以节省重建Dockerfile的时间。这是一种隐藏供应代码的方法。
  • 容器:虚拟操作系统本身,你可以ssh到它并运行你想要的任何命令,就好像它是一个真实的环境。您可以从同一个Image运行1000多个容器。

12
投票

容器只是一个可执行的二进制文件,它将由主机OS在一组限制下运行,这些限制是使用知道如何告诉OS应用哪些限制的应用程序(例如,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)

© www.soinside.com 2019 - 2024. All rights reserved.