在 Docker 中,容器和镜像有啥区别? [复制]
Posted
技术标签:
【中文标题】在 Docker 中,容器和镜像有啥区别? [复制]【英文标题】:In Docker, what's the difference between a container and an image? [duplicate]在 Docker 中,容器和镜像有什么区别? [复制] 【发布时间】:2014-02-25 06:07:31 【问题描述】:Docker 中的容器和镜像有什么区别?在Get started with Docker tutorial 中都使用了这两个术语,但我不明白其中的区别。
有人能解释一下吗?
【问题讨论】:
【参考方案1】:简单来说。
图片 -
文件系统和配置(只读)应用程序,用于 创建容器。 More detail.
容器 -
这些是 Docker 镜像的运行实例。容器运行实际 应用程序。一个容器包括一个应用程序及其所有 依赖项。它与其他容器共享内核并运行为 主机操作系统上用户空间中的一个隔离进程。 More detail.
需要注意的其他重要条款:
Docker 守护进程 -
在管理建筑物的主机上运行的后台服务, 运行和分发 Docker 容器。
Docker 客户端 -
允许用户与 Docker 交互的命令行工具 守护进程。
Docker 商店 -
Store 是 Docker 镜像的注册表。你可以 将注册表视为所有可用 Docker 映像的目录。
一张图片胜过一千个字。
(更深入的了解请阅读this。)
总结:
从 Docker 中心拉出 图像 或从 Dockerfile 构建 => 提供 Docker 图像(不可编辑)。 运行镜像 (docker run image_name:tag_name
) => 提供运行镜像,即容器(可编辑)
【讨论】:
未经授权请勿复制粘贴他人原创作品 我添加了与您的答案类似的 docker flow,没有复制粘贴。无论如何,现在已经删除了。你现在一定感到很满足。 一张图抵得上一千个字。 @XiaojieZhou 谢谢,在回答中提到了你的评论。【参考方案2】:图片是用您的手机拍摄的照片。 容器就是电话。
【讨论】:
这比有用更令人困惑。 大声笑,我能说什么..我仍然得到图片:D 这是一个非常错误的类比【参考方案3】:图像:运行容器所需的文件系统和元数据。它们可以被认为是一种应用程序打包格式,包括运行应用程序的所有依赖项,以及执行该应用程序的默认设置。元数据包括要运行的命令的默认值、环境变量、标签和运行状况检查命令。
容器:独立应用程序的实例。容器需要镜像来定义其初始状态,并使用镜像中的只读文件系统以及容器特定的读写文件系统。运行中的容器是一个正在运行的进程的包装器,为该进程提供文件系统、网络和 PID 等名称空间。
当您执行 docker run
命令时,您会在命令行上提供一个图像以及任何配置,并且 docker 根据您提供的该图像定义和配置返回一个容器。
参考:对于 docker 引擎,图像只是一个图像 id。这是一个独特的不可变哈希。对图像的更改会导致创建新的图像 ID。但是,您可以有一个或多个指向图像 id 的引用,这与符号链接不同。并且这些引用可以更新以指向新的图像 ID。请注意,当您创建容器时,docker 将在创建容器时解析该引用,因此您无法更新正在运行的容器的映像。相反,您创建一个新图像,并基于该新图像创建一个新容器。
层:再深入一点,你就有了文件系统层。 Docker 使用分层文件系统组装图像。每一层都是对文件系统的只读更改集,并且该层由唯一的哈希表示。使用这些只读层,多个图像可以扩展另一个,只有这些图像之间的差异需要存储或通过网络传输。当 Docker 容器运行时,它会接收到该容器特有的容器特定读写文件系统层,并且所有镜像层都使用联合文件系统组装在一起。通过每一层处理一次读取,直到找到文件,找到删除,或者在底层找不到文件。写入执行从图像只读层到容器特定读写层的写时复制。并且将删除记录为对容器特定读写层的更改。构建镜像的一个常见步骤是根据之前的镜像文件系统状态在临时容器中运行命令,并将生成的容器特定层保存为新镜像中的层。
【讨论】:
【参考方案4】:官方的区别是容器是可写的最后一层,而下面的层只能读取,它们属于你的镜像。直观的区别在于 docker 实例是由您的 docker 守护程序虚拟化的实例,并且正在运行您的映像,它在内核的隔离部分中运行(此过程对您隐藏)。然而,图像是静态的,它不会运行,它只是一堆层(静态文件)。如果我们将此范式与面向对象编程相关联,则图像是您的类定义,而您的 docker 实例是您的类派生对象,驻留在内存中。
我写了一个教程来加强你对 docker 知识的直觉:
http://javagoogleappspot.blogspot.com/2018/07/docker-basics.html
【讨论】:
您可以拥有只读容器。【参考方案5】:容器基于图像。需要将图像传递给 Dockers 运行命令。
例子:
BusyBox图片
http://i.stack.imgur.com/eK9dC.png
在这里我们指定一个名为busybox
的图像。 Docker 在本地没有此映像,而是从公共注册表中提取它。
注册表是 Docker 客户端可以与之通信并从中下载映像的 Docker 映像目录。拉取镜像后,Docker 会启动一个容器并执行 echo hello world 命令。
【讨论】:
【参考方案6】:使用面向对象的编程类比,Docker 镜像和 Docker 容器之间的区别就像类和对象之间的区别一样。对象是类的运行时实例。同样,容器是图像的运行时实例。
一个对象在实例化时只被创建一次。同样,容器可以运行或停止。容器是根据映像创建的,但情况可能并非总是如此。以下示例创建 Apache 服务器映像、运行映像、列出映像,然后列出容器:
创建一个包含以下内容的 Dockerfile:
FROM httpd:2.4
安装 Apache 服务器
sudo docker build -t my-apache2 .
运行镜像
sudo docker run -it --rm --name my-running-app my-apache2
列出 Docker 镜像
sudo docker images
列出正在运行的 Docker 容器
docker ps
列出所有容器
docker ps -a
列出最新创建的容器
docker ps -l
【讨论】:
这是一个很好的类比。如果您了解 Java,它会有所帮助。我要说的是,一个镜像就像一个 AWS AMI,而一个容器是一个 EC2 实例(运行或停止)——但你必须了解 Amazon Web Services 才能理解这个类比。 正是我在阅读@cbare 答案时的想法。但它并不是 Java 独有的。 绝对是@phpguru。 AMI 与 EC2 实例的类比是关联 Docker Image 与 Docker 容器的另一种方式。 我认为这个类比是有缺陷的。 Java 中的类更多是关于如何创建对象的描述。如果你想将它与 docker 中的任何东西进行比较,我相信最好的匹配是 Dockerfile。另一方面,Docker 镜像存储 FS 的状态,更像是 Java 中的序列化对象,那么从镜像创建容器就像反序列化 Java 中存储的对象。总的来说,我认为这些概念差异太大,无法比较。【参考方案7】:DockerFile --(Build)--> DockerImage --(run)--> DockerContainer
DockerFile 是您或开发人员编写代码来做某事(例如安装)
Docker Image是你在构建 docker 文件时得到的。
Docker 容器是您在运行 Docker 映像时获得的
我们可以通过 pull 从 docker hub 获取 Docker Image,然后运行它来获取 container 。
【讨论】:
【参考方案8】:映像是根文件系统更改和相应执行参数的有序集合,可在容器运行时中使用。图片是只读的。
https://docs.docker.com/glossary/?term=image容器是图像的活动(或非活动,如果退出)有状态实例。
https://docs.docker.com/glossary/?term=container【讨论】:
词汇表的描述是有道理的,但我无法将docker tutorial 中的以下定义与此联系起来:容器是 Linux 操作系统的基本版本.映像是您加载到容器中的软件。 @orad 因为在教程中这是一个非常糟糕的描述。我会 ping Docker... 来自 git,Docker 中图像和容器之间的概念区分似乎是不必要和浪费的。他们都只是州。也许它可以更简洁地建模为 DAG,甚至只是一棵树。 docker概念混乱,shell中的参数也很混乱 @stackdave 我以为我是唯一一个这么想的人!【参考方案9】:Docker 镜像: 它包含有关如何构建和运行容器的命令列表和说明。所以基本上图像包含启动容器所需的所有数据和元数据(也称为蓝图)。如果不指定图像,我们就不能午餐容器。
$docker images centos
列出所有可用的centos版本。
Docker 容器: 容器是图像的午餐,所以我们可以说容器是图像的运行实例。 Container 是一个运行时构造,不像 Images 是构建时构造。
【讨论】:
【参考方案10】:图像 [像 vm]
用于创建容器的只读模板 由您或其他 Docker 用户构建 存储在 Docker Hub 或本地注册表中容器[像一台跑步机]
独立的应用平台 包含运行应用程序所需的一切 基于图片【讨论】:
【参考方案11】:在 Docker 中,一切都始于图像。映像是构成操作系统的每个文件,足以执行您需要执行的操作。传统上,您会安装一个完整的操作系统,其中包含您所做的每个应用程序的所有内容。使用 Docker,您可以将其配对,这样您就有一个小容器,其中包含足够的操作系统来完成您需要做的事情,并且您可以在计算机上高效地拥有大量这些。
使用docker images
查看已安装的映像,使用docker ps
查看正在运行的映像。
当您输入docker run
时,它会获取图像,并使其成为具有正在运行的进程的活容器。我倾向于使用:
docker run -ti
<image>:<tag>
bash
最后,图像有自己的 id 集,容器也有自己的 id 集 - 它们不会重叠。
【讨论】:
【参考方案12】:图像基本上是用于创建容器的不可变模板。通过考虑将图像转变为容器时发生的情况,更容易理解图像和容器之间的区别。
Docker 引擎获取图像并在顶部添加一个读写文件系统,然后初始化各种设置。这些设置包括网络选项(IP、端口等)、名称、ID 和任何资源限制(CPU、内存)。如果 Docker 引擎被要求运行容器,它也会在其中初始化一个进程。可以停止和重新启动容器,在这种情况下,它将保留所有设置和文件系统更改(但会丢失内存中的任何内容,并且所有进程都将重新启动)。因此,停止或退出的容器不与图像相同。
【讨论】:
【参考方案13】:图像是实时容器的冻结不可变快照。容器正在运行(或停止)某些图像的实例。
从名为“ubuntu”的基础镜像开始。让我们在 ubuntu 映像中交互地运行 bash 并创建一个文件。我们将使用 -i
和 -t
标志来为我们提供交互式 bash shell。
$ docker run -i -t ubuntu /bin/bash
root@48cff2e9be75:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@48cff2e9be75:/# cat > foo
This is a really important file!!!!
root@48cff2e9be75:/# exit
不要指望当您退出并重新启动映像时该文件会保留。您将从与之前开始时完全相同的定义状态重新开始,而不是从您离开的地方重新开始。
$ docker run -i -t ubuntu /bin/bash
root@abf181be4379:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@abf181be4379:/# exit
但是,现在不再运行的容器有状态并且可以保存(提交)到图像中。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abf181be4379 ubuntu:14.04 /bin/bash 17 seconds ago Exited (0) 12 seconds ago elegant_ardinghelli
48cff2e9be75 ubuntu:14.04 /bin/bash About a minute ago Exited (0) 50 seconds ago determined_pare
...
让我们从我们创建文件的容器 ID 48cff2e9be75 创建一个图像:
$ docker commit 48cff2e9be75 ubuntu-foo
d0e4ae9a911d0243e95556e229c8e0873b623eeed4c7816268db090dfdd149c2
现在,我们有了一个包含我们非常重要的文件的新图像:
$ docker run ubuntu-foo /bin/cat foo
This is a really important file!!!!
试试命令docker images
。您应该会看到您的新图像 ubuntu-foo
与我们开始使用的 ubuntu
标准图像一起列出。
【讨论】:
这个解释是迄今为止最清晰和最好的——提供了与解释行话的“文字游戏”相比的真实例子 同意。这是一个很棒的小教程。我以为在我注意到它是我的一个朋友写的之前。嗨@cbare! 顺便说一句,docker exec -t -i 48cff2e9be75 /bin/bash
回到容器
@Faccion 我收到错误消息:“来自守护程序的错误响应:容器 48cff2e9be75... 未运行”
您从 Ubuntu 映像创建了一个实例。那么这个 Ubuntu 就是人们所说的“主机操作系统”?假设我的系统在 CentOS 上运行。那不是主机操作系统,对吗?另外,每个容器都会复制 Ubuntu 映像吗?我猜不会创建副本,因为它会像虚拟机一样沉重。以上是关于在 Docker 中,容器和镜像有啥区别? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在 Docker 镜像名称中,Alpine、Jessie、Stretch 和 Buster 有啥区别?