走进Docker

走进Docker

1.1 前言

随着生产力的发展尤其是弹性架构的广泛应用(比如微服务),许多一流开发者都将应用托管到了应用容器上,比如Google、微软、亚马逊、腾讯、阿里、京东、美团和新浪。

图1-1

图1-2

图1-3

图1-4

图1-5

图1-6

1.2 无服务器计算服务趋势

从未来的发展方向来看,容器引擎将会越来越成为主流,哪怕不是弹性架构,托管到应用容器也将是一种趋势——因为更低的开发运维和托管成本以及对服务器的资源的优化配置。而且未来一个很大的趋势是——无服务器计算服务。

因为相对于软件、硬件在本地设备中的分裂,云计算的一大特性就是将服务构建在云上,供多种设备同时无缝调用。但事实上,云服务在发展的过程中还没能实现共融共通的理想——比如,各家的云服务是相对割裂的,开发者基于Google云服务构建的软件拿到亚马逊的AWS上也许就不能用了,阿里云的应用迁移到腾讯云可能就存在问题了;在任务执行层面,为防止互相干扰,云服务厂商在同一台服务器上执行多个任务时也会将它们隔离进行。很明显,这样的实际情况和云服务的初始理念相去甚远。而利用容器技术,软件可以快速在各类云服务和基础设施上转换。而且,当割裂问题被解决之后,软件也有望在瞬间获取大量的计算能力。

图1-7

而Docker,就是容器引擎中的佼佼者,并且已经得到了广泛的实践和应用。有了Docker之后,软件的开发工作将会变得更加容易。比如,开发者们在笔记本电脑上写完一个软件后,可以将它转移到云服务上运行而无需做出更改;无论是自己的服务器、数据中心还是Google、微软、阿里云的云计算服务器,开发人员都可以按自己的想法在任何基础设施之间转移自己的软件。这也是未来的一个愿景——机器和基础设施是可以互相替代的,整个互联网就是一个巨大的计算机。

1.3 Docker+ Kubernetes(K8s)正在成为云计算的主流

Kubernetes(简称K8s)诞生于谷歌,是一个开源的,用于管理云平台中多个主机上的容器化的应用,K8s的目标是让部署容器化的应用简单并且高效,其提供了应用部署、规划、更新、维护的机制。

K8s主要有以下特点:

  • 可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)

  • 可扩展: 模块化,插件化,可挂载,可组合

  • 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展

K8s衔着金钥匙出生,一诞生就广受欢迎,更是在2017,其打败了所有的竞争对手,赢得了云计算的战争——主流的云厂商基本上都纷纷放弃了自己造“轮子”的举动,终止了各自的容器编排工具,加盟了K8s阵营,其中包括Red
Hat、微软、IBM、阿里、腾讯、华为和甲骨文等。

而Docker+K8s,这一组合已经成为了云计算的主流,基于Docker+K8s的新型PaaS平台具有敏捷部署、弹性伸缩、灵活调度、故障自动恢复等优势,充分满足业务扩展中的资源支持,因此在短短两年之内,便从Docker
Swarm、Cloud Foundry Diego、Kontena、Apache Mesos、Amazon
ECS…等大量对手中脱颖而出,拿下了皇冠。

K8s和Docker的胜利意味着这是有史以来第一次,无论使用哪一种云平台,研发人员都可以拥有完全相同的计算环境。

1.4 打消偏见,迎接Docker

Docker是如此令人向往和引人深入,但是在国内,开发者普遍迁移到云端基本上也都是只用到了虚拟机等基础设施,其实大家都听说过Docker,但是总是有一道门槛挡在大家面前导致大家无法逾越或者产生了一些偏见:

  • 缺乏完整的系统的教程和实践,开发者普遍认为使用Docker很麻烦,只有大公司能用,门槛很高;

  • 云端容器服务产品用户体验不够,对于初学者门槛太高——这个太高指的是消化这些概念和理念,并且能够掌握和可控;

  • 对容器服务的认知还不够,对它的好处以及吸引之处还不太了解;

  • 认为对现有系统、架构改造太大,成本太高;

  • 认为Docker只是一种单纯的相对先进的技术,并不能给现有的开发带来什么改变;

为了让大家能够更好认知Docker,打消以上的偏见,以及更好的利用和使用Docker,本教程将先讲述Docker的一些概念、场景,然后再讲述搭建、使用步骤以及开发工作流,最后讲述如何结合代码框架进行本地运行以及托管到云端。

1.5 什么是Docker

Docker
是一个开源的应用容器引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在本地编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare
metal、OpenStack 集群和其他的基础应用平台。

简单的理解,Docker类似于集装箱,各式各样的货物,经过集装箱的标准化进行托管,而集装箱和集装箱之间没有影响。也就是说,Docker平台就是一个软件集装箱化平台,这就意味着我们自己可以构建应用程序,将其依赖关系一起打包到一个容器中,然后这容器就很容易运送到其他的机器上进行运行,而且非常易于装载、复制、移除,非常适合软件弹性架构。

图1-8

因此,就像船只、火车或卡车运输集装箱而不论其内部的货物一样,软件容器充当软件部署的标准单元,其中可以包含不同的代码和依赖项。
按照这种方式容器化软件,开发人员和 IT
专业人员只需进行极少修改或不修改,即可将其部署到不同的环境。

总而言之,Docker
是一个开放平台,使开发人员和管理员可以在称为容器的松散隔离的环境中构建镜像、交付和运行分布式应用程序。以便在开发、QA
和生产环境之间进行高效的应用程序生命周期管理。

1.6 Docker和虚拟机

我们先来看2个简单的图:

图1-9

如图所示,容器是一个应用层抽象,用于将代码和依赖资源打包在一起。多个容器可以在同一台机器上运行,共享操作系统内核,但各自作为独立的进程在用户空间中运行。与虚拟机相比,容器占用的空间较少(容器镜像大小通常只有几十兆),瞬间就能完成启动。

而虚拟机 (VM)
则是一个物理硬件层抽象,用于将一台服务器变成多台服务器。管理程序允许多个 VM
在一台机器上运行。每个 VM
都包含一整套操作系统、一个或多个应用、必要的二进制文件和库资源,因此占用大量空间。而且
VM 启动也十分缓慢。

其区别主要如下图所示:

图1-10

图1-11

我们再来看以下对比图:

图1-12

如上图所示,由于容器所需的资源要少得多(例如,它们不需要一个完整的
OS),所以它们易于部署且可快速启动。这使你能够具有更高的密度,也就是说,这允许你在同一硬件单元上运行更多服务,从而降低了成本。

在同一内核上运行的副作用是,你获得的隔离比 VM 要少。

镜像的主要目标是使环境(依赖项)在不同的部署中保持不变。
也就是说,可以在计算机上调试它,然后将其部署到保证具有相同环境的另一台计算机上。

借助容器镜像,可打包应用或服务并采用可靠且可重现的方式对其进行部署。可以说
Docker 不只是一种技术,还是一种原理和过程。

在使用Docker之前,我们经常会听到,“这个问题在开发环境是正常的!”。而在使用
Docker
后,你不会听到开发人员说:“为什么它能在我的计算机上使用却不能用在生产中?”。开发人员只需说“它在
Docker 上运行”,因为打包的 Docker 应用程序可在任何支持的 Docker
环境上执行,而且它在所有部署目标(例如,开发、QA、暂存和生产)上都按预期运行

1.6.1 容器和虚拟机共用

刚才我们讲述了容器和虚拟机的区别,其实将容器和虚拟机配合使用,可以为应用的部署和管理提供极大的灵活性,如下图所示。

图1-13

1.7 Docker的基本概念

1.7.1 镜像:一个特殊的文件系统

操作系统分为内核和用户空间。对于 Linux 而言,内核启动后,会挂载 root
文件系统为其提供用户空间支持。而 Docker 镜像(Image),就相当于是一个 root
文件系统。

Docker
镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像不包含任何动态数据,其内容在构建之后也不会被改变。

我们可以使用“docker image ls”来列出本机的镜像:

图1-14

Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。
镜像实际是由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。

比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。

在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。

因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

1.7.2 容器:镜像运行时的实体

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等

我们可以使用命令“docker ps” 来查看正在运行的容器列表:

图1-15

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据
,容器存储层要保持无状态化。

所有的文件写入操作,都应该使用数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,
使用数据卷后,容器可以随意删除、重新 run,数据却不会丢失。

图1-16

注意:容器在整个应用程序生命周期工作流中提供以下优点:隔离性、可移植性、灵活性、可伸缩性和可控性。
最重要的优点是可在开发和运营之间提供隔离

1.7.2 仓库:集中存放镜像文件的地方

镜像构建完成后,可以很容易的在当前宿主上运行,但是,如果需要在其他服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker
Registry 就是这样的服务。

一个 Docker Registry
中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。

所以说,镜像仓库是 Docker
用来集中存放镜像文件的地方,类似于我们之前常用的代码仓库。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本

我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以
latest 作为默认标签。

这里补充一下 Docker Registry 公开服务和私有 Docker Registry 的概念:

Docker Registry 公开服务是开放给用户使用、允许用户管理镜像的 Registry 服务。

一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry 。Docker 官方提供了
Docker Registry 镜像,可以直接使用做为私有 Registry 服务。

开源的 Docker Registry 镜像只提供了 Docker Registry API 的服务端实现,足以支持
Docker
命令,不影响使用。但不包含图形界面,以及镜像维护、用户管理、访问控制等高级功能。

关于Docker Hub

Docker Hub是Docker官方维护的一个镜像仓库,也是我们最常使用的Registry
公开服务,这也是默认的Registry服务。其拥有大量的高质量的官方镜像,网址为:https://hub.docker.com/

图1-17

我们可以在上面免费托管我们自己的私人镜像。不过,在国内访问 Docker Hub
可能会比较慢,因此国内也有一些云服务商提供类似于Docker
Hub的公开服务,比如腾讯云和阿里云,在后续的章节我们会介绍腾讯云的镜像仓库的使用。

1.8 Docker版本概述

使用Docker之前,我们得对其版本有个基本的了解。目前,Docker有两个版本:

  • 社区版(Docker Community Edition,简称CE,可以免费使用)

  • 企业版(Docker Enterprise Edition,简称EE,需要购买,面向企业,强调安全)

社区版(CE)非常适合希望个人、开发人员和小型团队,而Docker企业版(EE)专为企业开发和IT团队而设计,以在生产中大规模构建,发布和运行关键业务的应用程序。在本书中,均使用Docker
CE进行演示和讲解。


  转载请注明: 麦扣官方文档 走进Docker

 上一篇
Docker最全教程之使用Node.js搭建团队技术文档站(二十三) Docker最全教程之使用Node.js搭建团队技术文档站(二十三)
前言各种编程语言均有其优势和生态,有兴趣的朋友完全可以涉猎多门语言。在平常的工作之中,也可以尝试选择相对适合的编程语言来完成相关的工作。 在团队技术文档站搭建这块,笔者尝试了许多框架,最终还是选择了Hexo,主要是由于其丰富的主题和插件,并
下一篇 
Docker最全教程之使用PHP搭建个人博客站点(二十二) Docker最全教程之使用PHP搭建个人博客站点(二十二)
目录 官方镜像 编写简单的Hello world! 编写Hello world! 编写Dockerfile 构建并运行 直接使用PHP Docker镜像运行PHP脚本 构建自己的WordPress镜像用于搭建个人博客站点
  目录