使用Docker时,我们从一个基础镜像开始。我们启动它,进行更改,这些更改会被保存在不同的层中,形成另一个镜像。
因此,我最终拥有一个用于PostgreSQL实例的镜像和一个用于Web应用程序的镜像,对其进行的更改将继续存在。
什么是容器?
使用Docker时,我们从一个基础镜像开始。我们启动它,进行更改,这些更改会被保存在不同的层中,形成另一个镜像。
因此,我最终拥有一个用于PostgreSQL实例的镜像和一个用于Web应用程序的镜像,对其进行的更改将继续存在。
什么是容器?
一个镜像的实例被称为容器。你拥有一张照片,它是由多个层次组成的。如果你启动这张照片,你就会得到一个正在运行的该镜像的容器。你可以同时拥有多个相同镜像的运行中容器。
你可以使用docker images
命令查看所有镜像,而使用docker ps
命令则可以查看正在运行的容器 (使用docker ps -a
命令可以查看所有容器)。
因此,镜像的运行实例即是容器。
以下是我关于自动化Docker部署(已存档)的文章内容:
在Docker中,有镜像和容器两个概念。它们紧密相关但又不同。对我来说,理解这种二分法极大地澄清了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
需要注意的一些事情:
用编程的比喻来说,如果一个镜像是一个类,那么一个容器就是该类的实例——一个运行时对象。容器是您使用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 ps
仅输出正在运行的容器。您可以使用docker ps -a
查看所有容器(正在运行或已停止)。--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 rm [CONTAINER_ID]
命令删除无用的已停止容器。docker rmi [IMAGE_ID]
命令删除无用已停止容器背后的镜像。docker system prune
命令清除了所有东西。 - Rami Alloush虽然最简单的理解容器就是运行的镜像,但这并不是完全准确的。
实际上,镜像只是一个模板,可以被转换成容器。为了将镜像转换为容器,Docker引擎会在其上添加可读写的文件系统,并初始化各种设置,包括网络端口、容器名称、ID和资源限制。正在运行的容器具有当前执行的进程,但容器也可以被停止(或按Docker的术语说是“退出”)。退出的容器与镜像不同,因为它可以重新启动,保留其设置和任何文件系统更改。
docker create
命令。 - Adrian Mouat也许解释整个工作流程可以有所帮助。
一切都始于 Dockerfile。Dockerfile 是镜像的源代码。
创建了 Dockerfile 后,您需要构建它以创建容器的镜像。 镜像只是“源代码” Dockerfile 的“编译版本”。
获取容器镜像后,您应使用注册表重新分发它。 注册表类似于 Git 存储库,您可以推送和拉取镜像。
接下来,您可以使用镜像运行 容器。 运行中的容器在许多方面非常类似于虚拟机(但没有hypervisor)。
Dockerfile → (构建) → 镜像 → (运行) → 容器.
Dockerfile: 包含一组 Docker 指令,用于按照您的喜好配置您的操作系统,并安装/配置所有软件。
镜像: 编译后的 Dockerfile。可以节省您每次需要运行容器时重新构建 Dockerfile 的时间。并且它也是隐藏您配置代码的一种方式。
容器: 虚拟操作系统本身。您可以 ssh 进入其中并运行任何命令,就像它是一个真实环境一样。您可以从同一个镜像运行 1000 多个容器。
以下是端到端的工作流程,显示各个命令及其相关输入和输出。这应该能够澄清图像和容器之间的关系。
+------------+ docker build +--------------+ docker run -dt +-----------+ docker exec -it +------+
| Dockerfile | --------------> | Image | ---------------> | Container | -----------------> | Bash |
+------------+ +--------------+ +-----------+ +------+
^
| docker pull
|
+--------------+
| Registry |
+--------------+
docker image ls
列出您可以执行命令的容器:
docker ps
尽管我已经阅读了这里所有问题的答案,但我仍然无法理解图像和层 的概念。最终我偶然发现了Docker的出色文档(当然啦!)。
该文档中的示例确实是理解整个概念的关键。由于该文章很长,因此我将总结需要真正掌握以获得清晰度的关键要点。
图像:Docker镜像由一系列只读层构建而成
层:每个层代表镜像的Dockerfile中的一条指令
示例
:下面的Dockerfile包含四个命令,每个命令都创建了一个层。
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
重要的是,每个层与它之前的层之间仅有差异。
因此,容器与镜像之间的主要区别是顶部可写层。添加新数据或修改现有数据的所有写入容器的操作都存储在该可写层中。删除容器时,可写层也将被删除。底层镜像保持不变。
从磁盘大小的角度理解图像和容器
要查看正在运行的容器的大约大小,您可以使用 docker ps -s
命令。您将获得 size
和 virtual size
作为输出之一:
Size:每个容器可写层使用的(磁盘上的)数据量
Virtual Size:容器使用的只读图像数据的数据量。多个容器可能共享某些或所有只读图像数据。因此,这些数据不是可加的。即,您不能将所有虚拟大小相加以计算图像占用了多少磁盘空间
另一个重要的概念是写时复制策略
如果文件或目录存在于镜像内的较低层,并且另一层(包括可写层)需要读取它,则直接使用现有文件。当另一层(构建镜像或运行容器时)第一次需要修改该文件时,该文件被复制到该层并进行修改。
希望这能够帮助像我这样的其他人。
简单来说,如果一张图片是一个类,那么一个容器就是该类的一个运行时对象实例。
一个容器只是一个可执行二进制文件,由主机操作系统在使用应用程序(例如Docker)预设的一组限制下运行。这个应用程序知道如何告诉操作系统应该应用哪些限制。
典型的限制与进程隔离、安全相关(例如使用SELinux保护)以及系统资源相关(内存、磁盘、CPU和网络)有关。
直到最近,只有基于Unix的系统内核支持在严格限制下运行可执行文件的能力。因此,今天大多数容器讨论都涉及Linux或其他Unix发行版。
Docker是那些应用程序之一,它知道如何告诉操作系统(主要是Linux)在什么限制下运行可执行文件。可执行文件包含在Docker镜像中,这只是一个tar文件。该可执行文件通常是Linux发行版用户空间的简化版本(如Ubuntu、CentOS、Debian等),预配置了一个或多个应用程序的运行环境。
尽管大多数人使用Linux作为可执行文件的基础,但只要主机操作系统的内核能够运行它(参见使用scratch创建简单基础镜像),它也可以是任何其他二进制应用程序。无论Docker镜像中的二进制文件是操作系统用户空间还是仅仅是一个应用程序,在操作系统主机看来,它只是另一个进程,由预设的操作系统边界控制的包含进程。因此,容器只是以受限模式运行的进程,类似于chroot所做的。
在我看来,Docker与任何其他容器技术不同之处在于其存储库(Docker Hub)及其管理工具,这使得使用容器非常容易。
请参见Docker(软件)。
Docker 的核心概念是让创建“机器”变得容易,这些“机器”可以被视为容器。容器有助于可重用性,允许您轻松地创建和销毁容器。
镜像描述了容器在每个时间点的状态。因此,基本的工作流程是: