《深入理解Docker》 笔记
镜像与容器
图6.1从顶层设计层面展示了镜像和容器间的关系。通常使用docker container run和docker service create命令从某个镜像启动一个或多个容器。一旦容器从镜像启动后,二者之间就变成了互相依赖的关系,并且在镜像上启动的容器全部停止之前,镜像是无法被删除的。尝试删除镜像而不停止或销毁使用它的容器,会导致下面的错误。
$docker image rm <image-name>
Error response from daemon:conflict: unable to remove repository reference "<image-name>"(must force) - container <container-id> is using its referencled image <image-id>
关于last
首先,如果没有在仓库名称后指定具体的镜像标签,则Docker 会假设用户希望拉取标签为latest的镜像。
其次,标签为latest 的镜像没有什么特殊魔力!标有 latest标签的镜像不保证这是仓库中最新的镜像!例如,Alpine仓库中最新的镜像通常标签是edge。通常来讲,使用latest标签时需要谨慎!
从非官方仓库拉取镜像也是类似的,读者只需要在仓库名称面前加上Docker Hub的用户名或者组织名称。下面的示例展示了如何从tu-demo仓库中拉取v2这个镜像,其中镜像的拥有者是 Docker Hub账户nigelpoulton,一个不应该被信任的账户。
容器 VS 虚拟机
容器和虚拟机都依赖于宿主机才能运行。宿主机可以是笔记本,是数据中心的物理服务器,也可以是公有云的某个实例。在下面的示例中,假设宿主机是一台需要运行4个业务应用的物理服务器。
在虚拟机模型中,首先要开启物理机并启动Hypervisor 引导程序(本书跳过了 BIOS和Bootloader代码等)一旦Hypervisor启动,就会占用机器上的全部物理资源,如CPU 、RAM存储和NIC。Hypervisor接下来就会将这些物理资源划分为虚拟资源,并且看起来与具实物理资源完全一致。然后Hypervisor会将这些资源打包进一个叫作虚拟机(VM)的文件件结构当中。这样用户就可以使用这些虚拟机,并在其中安装操作系统和应用。前面提到需要在物理机上运行4个应用,所以在Hypervisor之上需要创建4个虚拟机并安装4个操作系统、然后安装4个应用。当操作完成后,结构下图。
而容器模型则略有不同。
服务器启动之后,所选择的操作系统会启动。在 Docker 世界中可以选择Linux,或者内核支持内核中的容器原语的新版本Windows。与虚拟机模型相同,OS 也占用了全部硬件资源。在OS层之上,需要安装容器引擎(如 Docker )。容器引擎可以获取系统资源,比如进程树、文件系统以及网络栈,接着将资源分割为安全的互相隔离的资源结构,称之为容器。每个容器看起来就像一个真实的操作系统,在其内部可以运行应用。按照前面的假设,需要在物理机上运行4个应用。因此,需要划分出4个容器并在每个容器中运行一个应用 结构如下图
从更高层面上来讲,Hypervisor是硬件虚拟化(Hardware Virtualization)——Hypervisor将硬件物理资源划分为虚拟资源;
另外,容器是操作系统虚拟化(OS Virtualization)——容器将统资源划分为虚拟资源。
虚拟机的额外开销
基于前文所述内容,接下来会着重探讨Hypervisor模型的一个主要回题。
首先我们的目标是在一台物理机上运行4个业务相关应用。每种模型示例中都安装了一个操作系统或者 Hypervisor(一种针对虚拟机高度优化后的操作系统)。截至目前,两个模型还很相似,但是也就到此为止了。
虚拟机模型将底层硬件资源划分到虚拟机当中。每个虚拟机都是包含了虚拟 CPU、虚拟RAM、虚拟磁盘等资源的一种软件结构。因此,每个虚拟机都需要有自己的操作系统来声明、初始化并管理这些虚拟资源。但不幸的是,操作系统本身是有其额外开销的。例如,每个操作系统都消耗一点CPU、一点RAM、一点存储空间等。每个操作系统都需要独立的许可证,并且都需要打补丁升级,每个操作系统也都面临被攻击的风险。通常将这种现象称作OS Tax或者VMTax,每个操作系统都占用一定的资源。
容器模型具有在宿主机操作系统中运行的单个内核。在一台主机上运行数十个甚至数百个容器都是可能的—容器共享一个操作系统/内核。这意味着只有一个操作系统消耗CPU、RAM和存储资源,只有一个操作系统需要授权,只有一个操作系统需要升级和打补丁。同时,只有一个操作系统面临被攻击的风险。简言之,就是只有一份OS损耗!在上述单台机器上只需要运行4个业务应用的场景中,也许问题尚不明显。但当需要运行成百上千应用的时候,就会引起质的变化。
另一个值得考虑的事情是启动时间。因为容器并不是完整的操作系统,所以其启动要远比虚拟机快。切记,在容器内部并不需要内核,也就没有定位、解压以及初始化的过程——更不用提在内核启动过程中对硬件的遍历和初始化了。这些在容器启动的过程中统统都不需要!唯一需要的是位于下层操作系统的共享内核是启动了的!最终结果就是,容器可以在1s内启动。唯一对容器启动时间有影响的就是容器内应用启动所花费的时间。
这就是容器模型要比虚拟机模型简洁并且高效的原因了。使用容器可以在更少的资源上运行更多的应用,启动更快,并且支付更少的授权和管理费用,同时面对未知攻击的风险也更小。还有什么理由不喜欢容器呢!