虚拟化

开始之前应该先了解一下虚拟化技术:用户能以单个物理硬件系统为基础创建多个模拟环境或专用资源。一款名为”Hypervisor”(虚拟机监控程序)的软件可直接连接到硬件,从而将一个系统划分为不同的、单独安全环境,即虚拟机(VM)。虚拟机监控程序能够将计算机资源与硬件分离并适当分配资源

虚拟机(VM)

一种创建于物理硬件系统(位于外部或内部)、充当虚拟计算机系统的虚拟环境,它模拟出了自己的整套硬件,包括 CPU、内存、网络接口和存储器。 通过名为虚拟机监控程序的软件,用户可以将机器的资源与硬件分开并进行适当置备,以供虚拟机使用。

虚拟机监控程序

一种创建并运行虚拟机(VM)的软件。虚拟机监控程序(有时也称为 VMM)会将虚拟机监控程序的操作系统与虚拟机的资源分离开,并创建和管理这些 VM。
用作虚拟机监控程序的物理硬件被称为主机,而使用其资源的虚拟机则被称为客户机。
虚拟机监控程序将资源(如 CPU、内存和存储器)视为一组可以在现有的客户机之间或向新的虚拟机进行重新分配的资源池。
所有虚拟机监控程序都需要一些操作系统层面的组件才能运行虚拟机,如内存管理器、进程调度程序、输入/输出(I/O)堆栈、设备驱动程序、安全管理器以及网络堆栈等。
虚拟机监控程序将向每个虚拟机提供已分配的资源,并根据物理资源来管理 VM 资源的调度。物理硬件仍会继续执行任务,举例而言,在虚拟机监控程序管理调度时,CPU 将继续应 VM 的要求执行 CPU 指令。
多个不同的操作系统可以彼此并行运行,并与虚拟机监控程序共享相同的虚拟化硬件资源。这是虚拟化的主要优势。如果没有虚拟化,你只能在硬件上运行一个操作系统。
无论是传统供应商还是开源,虚拟机监控程序有很多选择。VMware 是一款热门的虚拟化产品,可以提供 ESXi 虚拟机监控程序和 vSphere 虚拟化平台。
基于内核的虚拟机(KVM)则是一种开源解决方案,它已内置于 Linux 内核中。其他方案包括开源 Xen 和 Microsoft Hyper-V。

Docker概述

Docker是一个用于开发,交付和运行应用程序的开放平台。Docker将应用程序与基础架构分开,从而可以快速交付软件。可以以与管理应用程序相同的方式来管理基础架构

Docker Engine概述

Docker Engine是一种开源容器化技术,用于构建和容器化你的应用程序。Docker Engine充当具有以下功能的客户端服务器应用程序:

  • 具有长时间运行的守护进程的服务器docker。
  • API,用于指定程序可以用来与Docker守护程序进行对话和指示的接口。
  • 命令行界面(CLI)客户端docker。

CLI使用Docker API通过脚本或直接CLI命令来控制Docker守护程序或与Docker守护程序进行交互。许多其他Docker应用程序都使用基础API和CLI。守护程序创建和管理Docker对象,例如映像,容器,网络和卷。

Docker平台

Docker(称为容器)提供了对软件和对其依赖的标准化打包。隔离安全性使你可以在给定主机上同时运行多个容器。容器是轻量级的,包含运行该应用程序所需所有内容,因此无需依赖主机上当前安装的内容。共享同一个OS kernel。

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

  • 使用容器开发应用程序及其支持组件。
  • 容器成为分发和测试你的应用程序的单元。
  • 准备就绪后,可以将应用程序作为容器或协调服务部署到生产环境中。无论你的生产环境是本地数据中心,云提供商还是两者的混合,其工作原理都相同。

    Docker架构

    Docker使用客户端-服务器架构。Docker客户端与Docker守护进程进行对话,该守护进程完成了构建,运行和分发Docker容器的繁重工作。Docker客户端和守护程序可以 在同一系统上运行,或者可以将Docker客户端连接到远程Docker守护程序。Docker客户端和守护程序在UNIX套接字或网络接口上使用REST API进行通信。另一个Docker客户端是Docker Compose,它使你可以处理由一组容器组成的应用程序。
    image.png

    Docker守护程序(Docker daemon)

    Docker守护程序(dockerd)侦听Docker API请求并管理Docker对象,例如图像,容器,网络和卷。守护程序还可以与其他守护程序通信以管理Docker服务。

    Docker客户端(Docker registries)

    Docker客户端(docker)是许多Docker用户与Docker交互的主要方式。当你使用诸如之类的命令时docker run,客户端会将这些命令发送到dockerd,以执行这些命令。该docker命令使用Docker API。Docker客户端可以与多个守护程序通信。

    Docker对象

    使用Docker时,可以创建和使用映像,容器,网络,卷,插件和其他对象。本节是其中一些对象的简要概述。

    Images(镜像)

    一个映像是用于创建一个Docker容器指令的只读模板。通常,一个映像基于另一个映像,并进行一些其他自定义。例如,你可以基于该ubuntu 映像构建映像,但安装Apache Web服务器和你的应用程序,以及运行该应用程序所需的配置详细信息。
    你可以创建自己的图像,也可以仅使用其他人创建并在注册表中发布的映像。要构建自己的映像,你可以 使用简单的语法创建一个Dockerfile,以定义创建映像并运行它所需的步骤。Dockerfile中的每条指令都会在映像中创建一个层。当你更改Dockerfile并重建映像时,仅重建那些已更改的层。与其他虚拟化技术相比,这是使映像如此轻巧,小型和快速的部分原因。

    Containers(容器)

    容器是映像的可运行实例。你可以使用Docker API或CLI创建,启动,停止,移动或删除容器。你可以将容器连接到一个或多个网络,将存储连接到它,甚至根据其当前状态创建一个新映像。
    默认情况下,容器与其他容器及其主机之间的隔离度相对较高。你可以控制容器的网络,存储或其他底层子系统与其他容器或与主机的隔离程度。
    容器由其映像以及在创建或启动时为其提供的任何配置选项定义。删除容器后,未存储在持久性存储中的状态更改将消失。

    示例docker run命令

    以下命令运行一个ubuntu容器,以交互方式附加到本地命令行会话,然后运行/bin/bash
    1. $ 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用Go编程语言编写,并利用Linux内核的多种功能来交付其功能。Docker使用一种称为的技术namespaces来提供称为容器的隔离工作区。运行容器时,Docker会为该容器创建一组 名称空间container。
    这些名称空间container提供了一层隔离。容器的每个方面都在单独的名称空间container中运行,并且对其的访问仅限于该名称空间container。

我们都知道,操作系统分为内核用户空间。对于 Linux 而言,内核启动后,会挂 载 root 文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于 是一个 root 文件系统。比如官方镜像 ubuntu:14.04 就包含了完整的一套 Ubuntu 14.04 最小系统的 root 文件系统。
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资 源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境 变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变

分层存储

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS的技术,将其设计为分层存储的架构。所以 严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其 实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作, 实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西, 任何额外的东西应该在该层构建结束前清理掉。 分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

镜像与容器

镜像是静态的定义,容器是镜像运行时的实体。容器可以被 创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、 自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。

容器持久化存储

每一个容器运行时,是以镜像为 基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。 容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此, 任何保存于容器存储层的信息都会随容器删除而丢失。
容器不应该向其存储层内写入任何数据,容器存储 层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器可以随意删除、重新 run ,数据却不会丢失。

仓库

Docker Registry

镜像构建完成后,可以很容易的在当前宿主上运行,但是,如果需要在其它服务器 上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多 个标签(Tag);每个标签对应一个镜像。
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的 各个版本。我们可以通过 <仓库名>:<标签>的格式来指定具体是这个软件哪个版 本的镜像。如果不给出标签,将以 latest 作为默认标签。
以 Ubuntu 镜像 为例, ubuntu 是仓库的名字,其内包含有不同的版本标签, 如,14.04 , 16.04 。我们可以通过 ubuntu:14.04 ,或者 ubuntu:16.04 来具体指定所需哪个版本的镜像。如果忽略了标签,比如 ubuntu ,那将视为 ubuntu:latest 。
仓库名经常以 两段式路径 形式出现,比如 jwilder/nginx-proxy ,前者往往意 味着 Docker Registry 多用户环境下的用户名,后者则往往是对应的软件名。但这 并非绝对,取决于所使用的具体 Docker Registry 的软件或服务。

Docker Registry 公开服务

Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。
最常使用的 Registry 公开服务是官方的 Docker Hub,这也是默认的 Registry,并拥有大量的高质量的官方镜像。除此以外,还有 CoreOS 的 Quay.io,CoreOS 相 关的镜像存储在这里;Google 的 Google Container Registry,Kubernetes 的镜像 使用的就是这个服务。
由于某些原因,在国内访问这些服务可能会比较慢。国内的一些云服务商提供了针对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为加速器。常见的有阿里云加速器DaoCloud 加速器灵雀云加速器等。使用加速器会直接从国仓库22内的地址下载 Docker Hub 的镜像,比直接从官方网站下载速度会提高很多。
国内也有一些云服务商提供类似于 Docker Hub 的公开服务。比如 时速云镜像仓库网易云镜像服务DaoCloud 镜像市场阿里云镜像库等。

私有 Docker Registry

除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。在后面会有进一步的搭建私有 Registry 服务的示例教程。
开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持 docker 命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、 访问控制等高级功能。在官方的商业化版本 Docker Trusted Registry 中,提供了这些高级功能。