logo学习随笔

【译】Docker 简介

December 30, 2019

简述

Docker 是集开发、发布、执行应用功能的一个开放平台。Docker 能够帮我们将应用和基础设施分离来达到更快的交付。有了 Docker,我们可以像管理基础设施一样管理我们的软件。有了 Docker 快速发布、测试、部署代码的优势,我们可以显著减少从编写代码到在生产环境执行的时间间隔。

Docker 平台

Docker 提供了在松散隔离的环境(被称作容器:container)中打包执行应用的能力。隔离和安全能力允许我们在一台宿主机上同时运行多个容器。容器本身是轻量的,它们不需要管理程序额外的负载,直接在宿主机的内核上运行。这意味着与虚拟机相比,我们可以在给定的硬件组合上运行更多容器。甚至我们可以在实际上是虚拟机的宿主机上运行 Docker 容器。

Docker 提供了工具和平台来管理容器的生命周期:

  • 使用容器开发应用程序和它支持的组件
  • 容器时发行和测试应用的单元
  • 准备就绪后,将应用程序作为容器或编排的服务部署到生产环境。无论生产环境是本地数据中心,云厂商,还是两者的结合,它们的工作原理都是相同的。

Docker 引擎

Docker 引擎是一个拥有下面主要功能的客户端程序:

  • 一种长期运行的称为守护进程的程序服务(dockerd 命令)
  • REST API,指定程序可以用来与守护进程通信并指示其操作的接口
  • 命令行接口(CLI)客户端(docker 命令)

engine components flow

CLI 使用 Docker REST API 通过脚本或直接 CLI 命令行来控制 Docker 守护进程或与 Docker 守护进程进行通信。许多其他 Docker 应用都使用底层 API 和 CLI。

守护进程创建和管理 Docker 对象,例如镜像,容器,网络,和卷。

注意:Docker 是基于开源的 Apache 2.0 许可

更多信息查看下面的 Docker 架构

我们能用 Docker 来做什么

快速一致地发布应用程序

Docker 允许开发者使用提供了应用程序和服务的本地容器在标准化环境下工作,从而简化开发过程。容器非常适合持续集成/持续发布(CI/CD)的工作流。

考虑下面的场景:

  • 开发者在本地编写代码并通过 Docker 容器来与同事共享
  • 他们使用 Docker 将应用推送到测试环境并执行自动、手动的测试
  • 当开发者发现了问题,他们可以在开发环境修复问题并重新发布到测试环境进行测试和验证
  • 当测试完成,将修复后的程序推送给用户就像将更新的镜像推送到生产环境一样简单

响应式部署和扩容

Docker 基于容器的平台允许高度的移植性。Docker 容器可以在开发者自身的电脑上,在数据中心的物理或虚拟机上,在云厂商上或混合的环境下运行。

Docker 的可移植性和轻量的本质在真实环境下亦可以动态管理工作负载,根据商业需要进行扩容或回收应用。

在同一个硬件上运行更多工作负载

Docker 是轻量的、快速的。它为基于管理程序的虚拟机提供了可行的,经济划算的替代方案,所以我们可以拥有更多算力来实现我们的商业目标。Docker 非常适合高密度环境和中小型部署需要更少资源做更多事情的场景。

Docker 架构

Docker 采用客户端-服务端架构。Docker 客户端与做大量构建,运行,分发 Docker 容器工作的 Docker 守护进程通信。Docker 客户端和守护进程可以在同一系统运行,或 Docker 客户端连接一个远程的 Docker 守护进程。Docker 客户端和守护进程通过基于 UNIX 套接字或 网络接口的 REST API 通信。

architecture

Docker 守护进程

Docker 守护进程(dockerd)会监听 Docker API 请求并管理 Docker 镜像,容器,网络,卷等对象。一个守护进程也能够与其他守护进程通信来管理 Docker 服务。

Docker 客户端

Docker 客户端(docker)是 Docker 用户与 Docker 主要的交互方式。当使用如 docker run 等命令时,客户端发送这些命令至 dockerd 来执行。 docker 命令使用 Docker API。Docker 客户端可以与多个守护进程通信。

Docker 注册源

Docker 注册源保存了 Docker 镜像。Docker Hub 是公开的任何人可以使用的源,Docker 默认去 Docker Hub 寻找镜像。我们也可以使用隐私源。

当使用 docker pulldocker run 命令时,这些依赖的镜像会从配置的源拉取。当使用 docker push 命令,镜像会推送到配置的源。

Docker 对象

当使用 Docker 时,我们创建并使用镜像,容器,网络,卷,插件等对象。下面是部分对象的简单介绍。

镜像

镜像是一种只读的模板,通过指令来创建 Docker 容器。通常,一个镜像基于另外的镜像,并在上面增加一些自定义的特性。例如,我们可以基于 ubuntu 镜像,安装 Apache web 服务器和应用程序,并配置能让应用执行的配置项来创建一个新的镜像。

我们可以创建自己的镜像,或使用其他人创建发布的镜像。为了创建自己的镜像,可以创建通过一些简单语法定义创建,执行镜像步骤的 Dockerfile 。在 Dockerfile 中的每条指令都会在镜像中创建一个层级。当更新 Dockerfile 并重新创建镜像时,只有改变的那些层才会重新创建。这就是与其他虚拟化技术相比能够保持镜像轻量,小型,快速的原因。

容器

一个容器是一个可运行的镜像的实例。我们可以使用 Docker API 或 CLI 创建,启动,停止,移动或删除容器。我们可以把容器与一个或多个网络,存储连接,甚至可以基于当前的状态创建新的镜像。

默认情况下,一个容器与其他容器和它的宿主机都高度的隔离。我们可以控制容器的网络,存储,或其他容器、宿主机的底层子系统的隔离程度。

一个容器由其镜像以及在创建或启动时为其提供的任何配置选项定义。当一个容器被移除时,任何没有存储在持久化存储中的改变的状态会消失。

docker run 命令的例子

下面的命令运行一个 ubuntu 容器,附加交互的命令行会话,并执行 /bin/bash

docker run -i -t ubuntu /bin/bash

当执行这条命令时,以下是内部发生的过程(假设使用了默认的源配置):

  1. 如果本地没有 ubuntu 镜像,Docker 会从配置的源拉取,需要手动执行 docker pull ubuntu
  2. Docker 创建了一个新的容器,就像手动执行了 docker container create 命令。
  3. Docker 分配了一个可读写的文件系统到容器作为最后一层。这允许一个运行的容器在其内部文件系统创建,修改文件和目录。
  4. Docker 创建网络接口来连接容器到默认的网络(如果没有指定任何的网络选项)。这会分配一个 IP 地址给容器。默认情况下,容器可以使用宿主机的网络连接来连接外部网络。
  5. Docker 开启容器并执行 /bin/bash。因为容器运行时可交互,并且附在终端上(由于设置了-i-t 标识),可以输入指令得到返回的输出结果。
  6. 当输入 exit 来结束 /bin/bash 命令时,容器会暂停但并不会移除。可以再次启动或移除。

服务

服务允许我们通过多个 Docker 守护进程(多个 managerworker 组成的集群)来扩展容器。集群中的每个成员都是一个 Docker 守护进程,这些进程都使用 Docker API 通信。一个服务允许定义期望的状态,例如任何时候都必须保证可用的服务副本的数量。默认情况下,服务在所有 worker 节点都是负载均衡的。对于消费者,Docker 服务表现为单个应用。Docker 引擎在 Docker 1.12 及以上版本支持集群模式。

底层技术

Docker 是使用 Go 语言实现的,并采用了 Linux 内核的许多特性来提供它的功能。

命名空间

Docker 使用了 namespaces 的技术来提供称为容器的隔离的工作环境。当运行一个容器时,Docker 为该容器创建了一系列命名空间。

这些命名空间提供了一个隔离层。容器的每部分都在独立的命名空间下运行,它们的访问权限都被限制在该命名空间下。

Docker 引擎使用以下 Linux 中的命名空间:

  • pid namespace: 进程隔离(PID: 进程 ID)
  • net namespace: 管理网络接口(NET: 网络)
  • ipc namespace: 管理访问 IPC 资源(IPC: 进程间通信)
  • mnt namespace: 管理文件系统挂载点(MNT: 挂在)
  • uts namespace: 隔离内核和版本标识(UTS: Unix 分时系统)

控制组

Docker 引擎在 Linux 系统也会依赖称为控制组(cgroups)的技术。一个 cgroup 限制了一个应用指定的资源集合。控制组允许 Docker 引擎分享可用的硬件资源给容器,并有选择地实行限制和约束。例如,你可以限制指定容器的可用内存大小。

统一文件系统

统一文件系统(UnionFS),是通过创建层级进行操作的文件系统,使其非常轻便快速。Docker 引擎使用 UnionFS 为容器提供构建模块。Docker 引擎可以使用多种 UnionFS 变种,如 AUSF,btrfs,vfs,DeviceMapper。

容器格式化

Docker 引擎结合命名空间,控制组,统一文件系统包装成一个容器包装称为一个容器格式化。默认的容器格式化是 libcontainer

参考

https://docs.docker.com/engine/docker-overview/