Docker很火!很潮!目测很有前途!

于是天生折腾不已的笔者也跃跃欲试,粗浅了解之后,不由惊叹Docker之颠覆性,不由大开脑洞、大呼过瘾

此处,笔者作为一名Docker初学者,梳理了一些初级问题,并尽量用浅显的语言、根据自己的理解分析下,抛砖引玉


(一)Docker,你是啥

Docker本质上应该算是一种新型的App分发、安装、运行平台

在Docker之前,如我们所知,如果我要安装一个App,比如一个Java编写的小程序,那么需要先安装JDK,而后才可以运行这个App,JDK在这里其实就是依赖的环境,App与环境是强相关的。反映到我们的工作中,环境(服务器)是由运维工程师(SA)维护的,App则是由开发工程师(DEV)维护的,App与环境被割裂了,直接导致App的开发、运维成本高企、各种内耗与风险

Docker创造性地解决了这个问题,Docker的LOGO很形象地解释了Docker的功能:

  • 把App与环境封装在一起(集装箱)
  • 封装后可以被整体搬运(小鲸鱼扛集装箱)
  • App不再直接依赖于环境、操作系统,简化了接口(集装箱里面的货物不再杂七杂八堆放在甲板上,而是井井有条,大大提高空间利用率;而且集装箱是个标准件,集装箱与甲板之间的接口是规范而统一的,移植性强)

有了Docker,就可以以集装箱(镜像,Image)为单位整体式地管控App的开发、运维流程;Docker之于App,正如JVM之于Java,可以帮助开发者实现一处开发、多处运行;以后我们不再交付与运维App,我们交付与运维容器

(二)Docker核心使用流程是啥

Docker使用三部曲:Build、Ship、Run,请牢记这个口诀,精华尽在此间

  • Build:使用DockerFile方便、快捷地制作镜像(Image),把业务App封装起来,由于使用了「UFS」技术(见下文),Build过程是很轻量级的
  • Ship:通过镜像库,例如:Docker Hub,在不同的用户、环境之间传递、复用Image
  • Run:一次Build,各处Run

举个栗子:先Build一个App的Image,上传到镜像库,再下载到测试服务器,测试PASS后,再分发至生产服务器集群,立刻就可以Run,如果业务压力增加,只要启用更多的容器实例即可,分分钟实现扩容

(三)Docker核心工具链有哪些东西

  • Docker Engine,提供核心功能,例如:创建Image、启动容器
  • Docker Machine,我们知道Docker只能运行在Linux环境,那么如果我是Mac或者Win,我如果要使用Docker,最好的途径就是使用Docker Machine。它会帮我们创建一个虚拟Linux主机(作为Host),用以容纳Docker。另外一个场景,如果我想管理一批remote的Docker虚拟主机,那么也可以使用Docker Machine
  • Docker Swarm,管理Docker集群
  • Docker Compose,对于Docker而言,一般是一个容器容纳一个App,如果我有一组App构成一个组合型服务,那么就可以使用Compose构建multi-container App
  • Docker Hub,官方的中央镜像库

(四)执行如下命令时发生了什么

$docker run -i -t ubuntu /bin/bash
  • Docker Client连上Host里面的Docker Daemon
  • Docker Daemon从Docker Hub下载一个「ubuntu」镜像
  • 基于镜像创建容器:在镜像的基础上加载一个可读写层
  • 为容器创建网络接口、分配IP
  • 执行「/bin/bash」
  • Docker Daemon捕获容器内Bash执行的输出内容,传递给Docker Client,进而打印到用户本机终端中

(五)容器技术与传统的虚拟化技术(VM)的主要区别

简单讲,传统的VM技术是在一台主机(Host)上虚拟出多个GuestOS,再在GuestOS里面安装App,而Docker的多个容器是直接共享一个Host的,并利用特定的Linux技术,使这多个容器互相隔离、互不可见

使用容器技术后,不再需要GuestOS,大大减少了系统资源的损耗,提高了效率,而且App的启动速度大大加快(VM的话,必须先启动GuestOS,再启动App)

(六)Docker所依赖的一些核心技术

Docker依赖了三项Linux技术:UFS(Union File System)、cgroup、namespace

其中,cgroup与namespace是Linux Kernel所提供的feature,知名度比较高,作用也比较容易理解:

  • cgroup:以进程组为单位限制对资源(CPU / Mem / IO / etc)的使用
  • namespace:造成环境(pid / network / user / etc)隔离,使互不可见

比较有意思的是UFS,下面单独讲

(七)UFS技术是个啥?

UFS,Union File System,简单讲其作用就是把多个文件系统(文件夹)层叠起来,对外抽象成一个文件系统使用,而这一层层的文件系统,底下几层都是只读的,只有顶层才是读写的,并且上层文件可以over下层的同名文件

把玩过Ubuntu的同学都知道,有个叫Live Ubuntu的东西,就是个光盘,插到电脑光驱里面就可以直接运行Ubuntu了,还可以进行写操作哦!这个就是UFS的典型栗子:光盘上的Ubuntu系统作为UFS的底层,电脑上的硬盘作为UFS的上层,从用户的角度看,是一个完整的「已经安装好」的Ubuntu,一切的写操作,其实都落在了硬盘上。如果我改了一个系统文件,例如「/etc/hosts」,这个改动其实是落在硬盘上了,光盘上的「/etc/hosts」文件必须还是不可写的,然后实际上使用的呢?必须是上层的那个「/etc/hosts」文件咯

再来看Docker,如图所示,一目了然,整个镜像其实也是分层的,每一层都安装了一个/一些App,这些App一起叠加在一起构成一个完整的可以执行的App&环境。然后,Docker运行这个镜像时,其实只是加载这个镜像,并且在顶层加盖一层可读写的文件,从而构成Container

这样一来,Docker的Build命令,其实就是在一个基础镜像(Base Image)基础上,一层一层加盖新内容,这些新内容往往就是我们自己的App及其依赖的运行时。根据UFS,底下的基础镜像只是个只读文件而已,那么Build过程其实是很轻量级和快速的,不就是往上面贴药膏么?

(八)既然Docker不须要GuestOS,为嘛我看大部分的镜像都是基于一个Linux基础镜像呢

如上所述,镜像是层叠的,而最底层一般都是一个Linux操作系统,比如:Ubuntu
我的理解,所有的App都是安装在操作系统上的,那么它必然对操作系统的文件构成依赖,因此,Docker镜像的基础镜像,其实只是作为一个「rootfs」存在:一个基底、一个地基,用于给App提供容身之所

讲到这里,我们可以看到,如果宿主机上安装了多个容器,那么这些容器:

  • 通过UFS拥有各自的rootfs,即:各自的文件系统
  • 通过namespace使得各自容器中运行的线程互不可见
  • 通过cgroup使得各个容器对于宿主机资源的使用受限

于是,it works!

(九)Docker好基友,哪里找?

除了官方推出的「swarm」「compose」,就属k8s与CoreOS了:

  • Kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用。
  • CoreOS是一个Linux发行版,最大特点是CoreOS不是通过APT之类的包管理工具来安装App,它天生就使用容器的方式安装App,与Docker可以说是天作之合。然而,CoreOS现在推出了自家容器品牌:Rocket,看样子是要分手呢!

以上是笔者一些粗浅的认识,请各位看官猛拍 & 多多讨论

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注