2.2.1. 前言
Docker
是一个用于开发、发布和运行应用程序的开放平台。Docker
使你能够将应用程序与基础设施分离,以便能够快速交付软件。使用 Docker
,
开发人员可以像管理应用程序一样管理基础设施。通过利用 Docker
快速发布、测试和部署代码的方法,可以显著减少编写代码和在生产环境中运行代码之
间的延迟。
2.2.2. Docker 平台
Docker
提供了在称为容器(container
)的松散隔离环境中打包和运行应用程序的能力。隔离和安全性允许您在给定主机上同时运行多个容器。容器是
轻量级的,因为它们不需要 hypervisor
的额外负载,而是直接在主机的内核中运行。这意味着,与使用虚拟机相比,您可以在给定的硬件组合上运行更多
的容器。你甚至可以在实际上是虚拟机的主机中运行 Docker
容器!
2.2.3. Docker Engine
Docker Engine是一个客户端-服务器应用程序,包含以下主要组件:
- 服务器是一种称为守护进程(
dockerd
命令)的长时间运行的程序类型。 - 一个
REST API
,它指定程序可以使用的接口来与守护进程对话并指示它做什么。 - 命令行接口(
CLI
)客户机(docker
命令)
CLI
使用 Docker REST API
通过脚本或直接 CLI
命令控制或与 Docker
守护进程交互。许多其他 Docker
应用程序使用底层 API
和 CLI
。
守护进程创建和管理Docker对象,例如图像、容器、网络和卷。
2.2.4. 可以使用 Docker 做什么?
快速、一致地交付应用程序
Docker
通过允许开发人员使用提供应用程序和服务的本地容器在标准化环境中工作,从而简化了开发生命周期。容器非常适合持续集成和持续交付(CI/CD
)
工作流。
想想一下下面的场景:
- 开发人员在本地编写代码,并使用
Docker
容器与同事共享他们的工作。 - 他们使用
Docker
将应用程序推进到测试环境中,并执行自动化和手动测试。 - 当开发人员发现
bug
时,他们可以在开发环境中修复bug
,并将其重新部署到测试环境中进行测试和验证。 - 测试完成后,向客户提供修复就像将更新后的映像推送到生产环境一样简单。
2.2.5. Docker 架构
Docker
使用客户机-服务器架构。Docker客户机与 Docker守护进程通信,该守护进程负责构建、运行和分发Docker容器。Docker客户机和守护进程可以在
同一个系统上运行,也可以将Docker客户机连接到远程Docker守护进程。Docker客户机和守护进程使用REST API、UNIX套接字或网络接口进行通信。
2.2.5.1. Docker 客户端
Docker 是一个典型的 C/S 架构的应用程序,但在发布上,Docker 将客户端和服务器统一在同一个二进制文件中。不过,这只是对于 Linux 系统而言。在其他 平台如 Mac 上,Docker只提供客户端。
Docker 客户端一般通过 Docker command
来发起请求,另外,也可以通过Docker提供的一整套 RESTFul API
来发起请求,这种方式更多的被应用在应
用程序的代码中。
2.2.5.2. Docker daemon
Docker daemon 也可以被理解成 Docker Server,另外,常常使用 Docker Engine 来直接描述它。因为这实际上就是驱动这个 Docker 功能的核心引擎。
简单地说,Docker daemon 实现的功能就是接受客户端发来的请求,并实现请求所要求的功能,同时针对请求返回响应的结果。在功能的实现上,因为涉及了容器、 镜像、存储等多方面的内容,daemon 内部的机制会复杂很多,涉及了多个模块的实现和交互。
2.2.6. Docker 镜像
镜像是一个只读模板,带有创建Docker容器的指令。通常,一个映像基于另一个映像,并进行一些额外的定制。与容器相对应,如果说容器提供了一个完整的、隔离的 运行环境,那么镜像则是这个运行环境的静态体现,是一个还没有运行起来的 运行环境。
想对于传统的虚拟化的 ISO 镜像,Docker 镜像要轻量化很多,它只是一个可定制的 rootfs
。Docker 镜像是层级的并且是可服用的,这也是它的一个创新。
这在实际应用场景中极为有用,多数基于相同发行版本的镜像,在大多数文件的内容都是一样的。因此,在实际中会看到一个镜像大小是 500M,但是三个加一起的大
小甚至不足 1G,这就是层级的复用的体现。
Docker 镜像通常是通过 Dockerfile 来创建的,Dockerfile 提供了镜像内容的定制,同时也体现了层级关系的建立。另外,Docker 镜像也可以通过
docker commit
这样的命令来手动将修改后的容器生成镜像。
2.2.7. Docker 容器
容器(container
)是镜像(image
)的可运行实例。你可以使用 Docker API
或 CLI
创建、启动、停止、移动或删除容器。您可以将容器连接到一个
或多个网络,向其附加存储,甚至根据其当前状态创建新映像。
容器是由它的镜像以及在创建或启动它时提供给它的任何配置选项定义的。当移除容器时,对其状态的任何未存储在持久存储中的更改都会消失。
2.2.8. Docker Registry
Docker Registry 用于存储 Docker 镜像的仓库。它通常部署在互联网服务器或云端。通常,集装箱是需要通过游轮进行海洋传输到世界各地。而互联网时代的传 输则要方便很多,在镜像的传输过程中,Registry 就是这个传输的重要中转站。
Docker Hub
是一个任何人都可以使用的公共仓库,同 GitHub 一样。
2.2.9. Docker 底层实现
简单的说,Docker是建立在内核容器技术(Namespaces
和Cgroup
)的基础上。
2.2.9.1. Namespaces
Docker使用一种称为 Namespace
的技术来提供称为容器的隔离工作区。在运行容器时,Docker为该容器创建一组名称空间。
Namespace
是将内核的全局资源做封装,使得每个 Namespace
都有一份独立的资源,因此不同的进程在各自的 Namespace
内对统一资源的使用不
会互相干扰。
举个栗子,执行 sethostname
这个系统调用时,可以改变系统的主机名,这个主机名就是一个内个的全局资源。内核通过 UTS Namespace
,可以将不同的
进程分隔在不同的 UTS Namespace
中,在某个 Namespace
修改主机名时,另一个 Namespace
的主机名还是保持不变。
目前 Linux 内核总共实现了6中 Namespace
:
- IPC:隔离 System V IPC 和 POSIX 消息队列。
- Network:隔离网络资源
- Mount:隔离文件系统挂载点。
- PID:隔离进程的 ID。
- UTS:隔离主机名和域名。
- User:隔离用户 ID 和组 ID
2.2.9.2. Control groups
Linux上的Docker引擎还依赖于另一种称为控制组(cgroups
)的技术。cgroup
用于限制和隔离一组进程对系统资源的使用,也就是做资源 QoS,这些资源包
括 CPU、内存、block I/O 和网络带宽。