在工作中有接触过docker部署,但只限于简单的使用,对于docker不甚了解,只是大致知道它是一种进程级别的虚拟化技术,因此本文是我对Docker技术的整理和总结。Docker是时下热门的容器技术,相信作为一名开发人员,你也一定听说过或者使用过,很多人会把Docker理解为一个轻量级虚拟机,但其实Docker与虚拟机(例如VMware)是两种不同的计算机虚拟化技术,也有很多人会觉得,有了虚拟机,那为什么还要使用Docker呢?Docker和VMware 有什么区别呢?这些问题也是我开始接触Docker时所疑惑的。带着心里的一点点疑问,让我们一起来学习Docker吧。
什么是Docker
docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。简言之,就是可以在Linux上镜像使用的这么一个容器。说这么多,还是些官话,如果对虚拟化,沙箱之类的技术不是很了解的话,还是难以理解。不用着急,继续往下看。我会从硬件层面,逻辑层面,以及历史来阐明Docker到底是个啥东西,它解决了什么问题(既然它能替代VMware ,那肯定是解决了VMware解决不了的问题)
理解特点
首先明确技术要点,Docker技术就是基于容器的虚拟化技术,相对于其它虚拟化技术,它的特点是:
- 轻量级:单机可以轻松支持上百Container,让各种个位数虚拟化的方案相形见绌。
- 快速就绪:一秒以内启动,即使是以资源快速就绪著称的青云IAAS也无法相比。
- 弱安全(容器隔离):Docker能够对多种OS资源进行隔离,但是它本质上依托于内核,因此所有的内核漏洞都是Docker的致命伤。VMware就不存在这个问题。
- 简化配置:构建一次后打包后就可以用作测试环境,也可以用作生产环境或与预生产环境,可以省去很多测试环节。比如一台服务器可以进行测试多个版本的测试,不用等待
- 动态扩容:对与运维来说,可以快速的进行扩容,减少原利用率
从这几个特点可以看出Dcoker解决的问题,并不是某个技术问题。而是开发测试部署各个环境之间的交付的优化,主要偏向于运维部署方面的解决方案。如果是这样,那么回顾一下在没有Docker之前,项目从开发到上线的流程是怎么样的。两者做一个对比就能明白Docker所起的作用了。
项目部署
没有虚拟化技术的原始年代
在没有虚拟化技术的“远古”年代,如果我们要部署一个应用程序(Application),一般的步骤是怎么样的?我们得把项目打好包,然后准备一台物理服务器,然后在物理服务器上安装一个操作系统(Operating System)。然后把项目打好的包上传到服务器的某个目录,一般项目有自己需要的运行环境,例如数据库,Java的JRE,MQ等,还要把这些附带的中间件也要安装好,服务才能正常运行
在物理机上部署应用有以下几个缺点:
- 部署非常慢:因为我们得先准备硬件服务器,接着还要安装操作系统,然后再部署应用程序,而且应用程序还有很多的依赖软件,所以这个过程是比较慢的。当然你可以与其他服务共用已有的服务器
- 迁移和扩展太慢:当服务用户量增大需要迁移到新的服务器上,或者扩展应用,都要再准备其他的物理服务器,过程很麻烦,也很慢。
- 资源不可分配:我们把服务直接运行在OS之上时,是没办法对服务占用的CPU和内存做限制的,这就会导致当服务出现异常,例如CPU或内存飙升时,会影响到其它正常运行的服务
那么有什么办法可以解决这些问题吗?答案就是虚拟化技术
用虚拟机部署应用程序的年代
所谓虚拟化技术,就是在一台物理机计算机上,模拟出多台机器。它是通过操作系统的Hypervisor 技术实现,我们不用深究它是什么原理,但需要有一个大致的认识,虚拟机的虚拟化是硬件级别的虚拟化,它与宿主机不共享磁盘,内存和操作系统。虚拟机中需要安装自己的操作系统,如宿主机是Windows系统或Linux系统,虚拟机也可以安装Windows或Linux。宿主机和虚拟机逻辑上已经是两个个体了,只不过寄存在一台物理机上,共用同一台计算机的硬件设备。示意图如下
虚拟机的优点
- 可以把资源分配到不同的虚拟机,达到硬件资源的最大化利用
- 与直接在物理机上部署应用,虚拟更容易扩展应用。
- 云服务:通过虚拟机虚拟出不同的物理资源,可以快速搭建云服务。
虚拟机的缺点
- 虚拟机对物理服务器资源的消耗比较大,因为需要安装一个额外的操作系统,每台虚拟机都占用许多的服务器资源
- 虚拟机启动很慢,虚拟机和正常操作系统开关机一样是个耗时的操作
- 虚拟机部署并没有很好的解决物理机部署移植性的问题,当我们需要把服务移植到一个新的虚拟机上时,同样需要在新的虚拟机上安装服务运行环境,如数据库,JRE等。当然你也可以直接把原来的虚拟机做一份镜像拷贝过来。但虚拟机镜像比较大,也不是很方便
用Docker部署应用程序的年代
相对于虚拟机的笨重,Docker则更显得轻量化。Docker相比虚拟机为什么会这么轻?本质原因是虚拟机与Docker的虚拟化程度不一样。Docker是使用时下很火的Golang语言进行开发的,其技术核心是Linux内核的Cgroup,Namespace和AUFS类的Union FS等技术,这些技术都是Linux内核中早已存在很多年的技术,所以严格来说并不是一个完全创新的技术,Docker通过这些底层的Linux技术,对Linux进程进行封装隔离,而被隔离的进程也被称为容器,完全独立于宿主机的进程。所以Docker是容器技术的一种实现,也是操作系统层面的一种虚拟化,与虚拟机的通过一套硬件再安装操作系统完全不同。容器仅仅只在进程级别隔离硬件,也就是说Docker虚拟化技术它没有自己的OS,它本身只是操作系统上的一个进程,在这个进程中可以运行多个容器,每个容器相互隔离,容器和宿主机是共享操作系统。
这个结构跟虚拟机有些类似,但是实现上是有很大区别的,下面是物理机,虚拟机和Docker容器三种部署方式,服务器上架构的演进图,更加直观
虚拟机 VS 容器
传统物理机部署就不多说了,着重对比一下虚拟机和容器化的区别,简单来说: 容器和虚拟机具有相似的资源隔离和分配优势,但功能有所不同,因为容器虚拟化的是操作系统,而不是硬件,因此容器更容易移植,效率也更高。下面是一个详细的对比表格
特性 | 虚拟机 | 容器 |
---|---|---|
启动 | 分钟级 | 秒级 |
硬盘 | 一般为GB | 一般为MB |
性能 | 弱于容器 | 接近原生 |
支持量 | 一般为几十个 | 单机支持上千个容器 |
结构对比
通过Docker官网,我们知道了这么多Docker的优势,但是大家也没有必要完全否定虚拟机技术,因为两者有不同的使用场景。虚拟机更擅长于彻底隔离整个运行环境。例如,云服务提供商通常采用虚拟机技术隔离不同的用户。而 Docker通常用于隔离不同的应用 ,例如前端,后端以及数据库。对于两者无所谓谁会取代谁,而是两者可以和谐共存。
总结
从上面的容器结构图中,每一个App和Lib的组合,就是一个容器,所有和应用相关的依赖都会在容器中,因此移植非常方便。也就是Docker图标里面的一个集装箱。和虚拟机相比,容器有以下优点:
迅速启动
:没有虚拟机硬件的初始化,没有Guest OS的启动过程,可以节约很多启动时间,这就是容器的“开箱即用”。占用资源少
:没有运行Guest OS所需的内存开销,无需为虚拟机预留运行内存,无需安装、运行App不需要的运行库/操作系统服务,内存占用、存储空间占用都小的多。相同配置的服务器,如果运行虚拟机只能运行十多台的,通常可以运行上百个容器毫无压力——当然前提是单个容器应用本身不会消耗太多资源。
当然,和虚拟机相比,因为共用内核,只靠cgroup隔离,应用之间的隔离是不如虚拟机彻底的,如果某个应用运行时导致内核崩溃,所有的容器都会崩溃。而虚拟机内的应用崩溃,理论上是不会影响其它虚拟机以及上面运行的应用的,除非是硬件或者Hypervisor有Bug。Docker把App和Lib的文件打包成为一个镜像,并且采用类似多次快照的存储技术,例如aufs/device mapper/btrfs/zfs等,可以实现:
- 多个App可以共用相同的底层镜像(初始的操作系统镜像)
- App运行时的IO操作和镜像文件隔离;
- 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个App镜像可以同时用来运行无数个不同业务的容器。
出处:https://www.zhihu.com/question/28300645/answer/585166942
+---------+ +---------+ +---------+ +-----+ +-----+ +-----+
| abc.com | | def.com | | xyz.com | | DB1 | | DB2 | | DB3 |
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| | | | | |
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| abc | | def.com | | xyz.com | | DB1 | | DB2 | | DB3 |
| config | | config | | config | | conf| | conf| | conf|
| data | | data | | data | | data| | data| | data|
+----+----+ +----+----+ +----+----+ +--+--+ +--+--+ +--+--+
| | | | | |
+------------+------------+ +-------+-------+
| |
+------+------+ +------+------+
| Nginx Image | | MySQL Image |
+------+------+ +------+------+
| |
+----------------+----------------+
|
+------+-------+
| Alpine Image |
+------+-------+
上图是基于一个Alpine Linux的镜像,分别建立了Nginx和MySQL的镜像,并且挂载不同的配置/数据同时运行3个网站应用3个数据库应用的示意图。此外,Docker公司提供公共的镜像仓库(Docker称之为Repository),Github connect,自动构建镜像,大大简化了应用分发、部署、升级流程。加上Docker可以非常方便的建立各种自定义的镜像文件,这些都是Docker成为最流行的容器技术的重要因素。通过以上这些技术的组合,最后的结果就是,绝大部分应用,开发者都可以通过docker build创建镜像,通过docker push上传镜像,用户通过docker pull下载镜像,用docker run运行应用。用户不需要再去关心如何搭建环境,如何安装,如何解决不同发行版的库冲突——而且通常不会需要消耗更多的硬件资源,不会明显降低性能。这就实现了各个环境的标准化、这也是docker的图标为什么是集装箱的原因所在。 容器就是一个不错的解决方案,容器能成为开发与运维之间沟通的语言,因为容器就像一个集装箱一样,提供了软件运行的最小化环境,将应用与其需要的环境一起打包成为镜像,便可以在开发与运维之间沟通与传输。
Docker名词术语
Docker Client
: Docker提供给用户的客户端。Docker Client提供给用户一个终端,用户输入Docker提供的命令来管理本地或者远程的服务器。Docker Daemon
: Docker服务的守护进程。每台服务器(物理机或虚机)上只要安装了Docker的环境,基本上就跑了一个后台程序Docker Daemon,Docker Daemon会接收Docker Client发过来的指令,并对服务器的进行具体操作。Docker Images
: 俗称Docker的镜像,这个可难懂了。你暂时可以认为这个就像我们要给电脑装系统用的系统CD盘,里面有操作系统的程序,并且还有一些CD盘在系统的基础上安装了必要的软件,做成的一张 “只读” 的CD。Docker Registry
: 这个可认为是Docker Images的仓库,就像git的仓库一样,用来管理Docker镜像的,提供了Docker镜像的上传、下载和浏览等功能,并且提供安全的账号管理可以管理只有自己可见的私人image。就像git的仓库一样,docker也提供了官方的Registry,叫做Dock HubDocker Container
: 俗称Docker的容器,这个是最关键的东西了。Docker Container是真正跑项目程序、消耗机器资源、提供服务的地方,Docker Container通过Docker Images启动,在Docker Images的基础上运行你需要的代码。你可以认为Docker Container提供了系统硬件环境,然后使用了Docker Images这些制作好的系统盘,再加上你的项目代码,跑起来就可以提供服务了。 听到这里,可能你会觉得是不是有点像一个VM利用保存的备份或者快照跑起来环境一样,其实是挺像的,但是实际上是有本质的区别,后面我会细说。
Docker发展历史
2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫“dotCloud”的公司。这家公司主要提供基于PaaS的云计算技术服务。具体来说,是和LXC有关的容器技术。后来,dotCloud公司将自己的容器技术进行了简化和标准化,并命名为——Docker。Docker技术诞生之后,并没有引起行业的关注。而dotCloud公司,作为一家小型创业企业,在激烈的竞争之下,也步履维艰。正当他们快要坚持不下去的时候,脑子里蹦出了“开源”的想法。2013年3月,dotCloud公司的创始人之一,Docker之父,28岁的Solomon Hykes正式决定,将Docker项目开源。不开则已,一开惊人。越来越多的IT工程师发现了Docker的优点,然后蜂拥而至,加入Docker开源社区。Docker的人气迅速攀升,速度之快,令人瞠目结舌。开源当月,Docker 0.1 版本发布。此后的每一个月,Docker都会发布一个版本。到2014年6月9日,Docker 1.0 版本正式发布。这也意味着Docker的稳定性和可靠性已经基本满足了生产环境的运行需求。会议上同时发布Docker Image的镜像仓库Docker Hub,并指出已经有超过14,000个Docker化的应用存储在他们的publc registry中。此时的Docker,已经成为行业里人气最火爆的开源技术,没有之一。甚至像Google、微软、Amazon、VMware这样的巨头,都对它青睐有加,表示将全力支持。也是同样的2014年6月,基于谷歌内部强大的Borg系统而开发出来的kubernetes横空处世,刷新了人们对容器的理解。
其他容器技术
虽然 docker 把容器技术推向了巅峰,但容器技术却不是从 docker 诞生的。实际上,容器技术连新技术都算不上,因为它的诞生和使用确实有些年头了。下面的一串名称肯能有的你都没有听说过,但它们的确都是容器技术的应用。
- Chroot Jail:就是我们常见的 chroot 命令的用法。它在 1979 年的时候就出现了,被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。
- FreeBSD Jails:Freebsd Jail 实现了操作系统级别的虚拟化,它是操作系统级别虚拟化技术的先驱之一。
- Linux VServer:使用添加到 Linux 内核的系统级别的虚拟化功能实现的专用虚拟服务器。
- Solaris Containers:它也是操作系统级别的虚拟化技术,专为 X86 和 SPARC 系统设计。Solaris 容器是系统资源控制和通过 “区域” 提供边界隔离的组合。
- OpenVZ:OpenVZ 是一种 Linux 中操作系统级别的虚拟化技术。 它允许创建多个安全隔离的 Linux 容器,即 VPS。
- Process Containers:Process 容器由 Google 的工程师开发,一般被称为 cgroups。
- LXC:LXC 又叫 Linux 容器,这也是一种操作系统级别的虚拟化技术,允许使用单个 Linux 内核在宿主机上运行多个独立的系统。
- Warden:在最初阶段,Warden 使用 LXC 作为容器。 如今已被 CloudFoundy 取代。
- LMCTFY:LMCTY 是 Let me contain that for you 的缩写。它是 Google 的容器技术栈的开源版本。Google 的工程师一直在与 docker 的 libertainer 团队合作,并将 libertainer 的核心概念进行抽象并移植到此项目中。该项目的进展不明,估计会被 libcontainer 取代。
- Docker:Docker 是一个可以将应用程序及其依赖打包到几乎可以在任何服务器上运行的容器的工具。
- RKT:RKT 是 Rocket 的缩写,它是一个专注于安全和开放标准的应用程序容器引擎。