文章目录
Docker为什么产生?
Docker是容器 的标准化实现,容器是为了解决虚拟机 硬件资源的浪费,同时又保证了虚拟机 对软件的隔离。
虚拟机是硬件虚拟化 的实现技术,Docker是操作系统虚拟化即容器化 的实现技术。可能这里会有疑惑,为什么需要硬件虚拟化,是为了解决什么问题?而Docker又是如何解决硬件虚拟化存在的问题?带着这几个问题我们先去了解下硬件虚拟化 和容器化
硬件虚拟化
硬件虚拟化解决的问题
1.不同软件之间或者相同软件不同版本之间的冲突,将冲突的软件进行隔离
2.硬件性能过剩,希望将其最大限度的利用起来
3.操作系统上安装的软件,希望能完整的copy给其他人,而不用重新安装
硬件虚拟化定义
仿真出一台或者多台计算机的各种硬件,用户可以在这一台虚拟机上安装和运行操作系统(一般叫来宾操作系统,Guest OS
)和各种应用,并且把 Guest OS
和上面应用软件对硬件资源的访问转发到底层的硬件
上来实现
硬件虚拟化技术
VMware Workstation
,Oracle 的 VirtualBox ,
Microsoft 的 Virtual PC
。这类软件可以统称为Hypervisor
(虚拟机管理程序)即虚拟机
虚拟机的优点
- 硬件最大化利用
- 更易移植
- 更易拓展(比如云服务,利用虚拟机虚拟不同的物理资源)
虚拟机的缺点
- 每启动一个虚拟机,就会占用大量的内存和硬盘资源,即使不使用
- 为了管理各个虚拟机,又需要额外的内存资源
- 单台计算机上可运行的虚拟机数量有上限,随着虚拟机的增多,系统资源的浪费会加重
操作系统虚拟化即容器
容器化解决的问题
一般单台计算机上运行的虚拟机操作系统大多是一样的。可以让所有的虚拟机
都使用同一个操作系统底层,这样就避免了硬件资源的浪费。同时在共享操作系统底层的时候,虚拟机
之间的隔离性仍旧需要存在。所以提出**「操作系统层虚拟化------容器」**概念,就是为了解决这个问题。
容器化定义
容器化
就是应用程序级别的虚拟化技术。容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。
容器化技术历史
1979年
1979年,第一个Unix版本V7发布,在1979年的这个V7版本上,chroot这个系统调用被发明了出来,什么是chroot呢?就是改变一个进程及其子进程的根目录到另外一个目录下,在经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,这样有几个好处:
- 增强系统安全性,限制了用户进程的权限,使得进程不能访问一些特定的文件;
- 建立一个和原系统隔离的目录结构(是不是联想到了容器的隔离文件系统union gs),为进程指定一个单独的、新的文件系统上下文环境。
于是,Unix就具有了这种能力:为每个进程提供一个隔离的虚拟文件系统。Chroot在后来的1982年被新增到了BSD这个分支中。可见,在早期构建Unix系统的先驱们已经有了这种意识,就是隔离的意识。chroot可以认为是容器技术的鼻祖。
1999年
在这年,一家共享主机托管商提供了FreeBSD Jails的概念,顾名思义,就是将服务和客户端服务明确的区分开,实现安全性和可管理的便捷性,它允许将系统划分为几个独立的较小的系统,称之为Jail,并且这些小系统有独立的配置和IP地址。这就有容器的意思了。2000年,伴随FreeBSD4.0版的发布,正式对外公开。系统管理者可以使用jail(8)这个命令来调用这个服务。
2001年
该Linux出场了,GUN和Linux整合后迅速发展,这个时间点上Linux已经比较成熟了,Linux Vserver出现了,和Free BSD的Jails是相同的原理,可以对OS上的资源(文件系统、网络等)进行隔离划分。到了2001年,Linux通过对内核打补丁的方式实现了该种虚拟化,其实就是namespace机制,中间经过了很多次完善,最后的stable补丁在2006年发布。
2004年
Solaris属于Unix的一个变种,在2004年,Solaris上的虚拟化诞生了,初期称为Solaris container,Solaris的虚拟化技术由Sun公司开发,2004年2月同Solaris10版本对外发布,Sun公司在2009年被并购后落入了Oracle公司,Solaris11之后叫Solaris zones。从名字也能看出来,也是一种操作系统层面的轻量级虚拟化技术。
Solaris zones 是Native zone,kernel zone的统称,能够为你使你的应用在隔离的环境中运行,并实现有效的资源管理。几乎所有的Oracle用户都在使用Zone,广泛应用在生产环境中,从web app 到Oracle数据库实例都可以安装在zone里面。zone 技术为应用程序创建了虚拟的一层,可以将zone 称之为一个沙箱,我们安装的操作系统称为global-zone,在global zone里面可以创建很多独立的zone,称为non-globalzone,global zone 控制着操作系统内核,设备驱动,系统内存管理,文件系统等等并为non global zone 提供接口。非global zone 之间互相独立,互不影响,每一个zone 拥有自己的文件系统,进程空间,防火墙,网络配置等等,对于global zone 来说每一个non-global zone 是一个拥有一组资源并用zone ID命名的进程。Solaris zone 是一种轻量级的虚拟化技术,虚拟化的开销很小,所有的native zone 依赖于操作系统内核,kernelzone 可以拥有独立的内核版本:
2005: Open VZ (Open Virtuzzo)
2005年,SWsoft发布了Open VZ,OpenVZ是开源软件,是基于Linux平台的操作系统级服务器虚拟化解决方案。OpenVZ采用SWsoft的Virtuozzo虚拟化服务器软件产品的内核,Virutozzo是SWsoft公司提供的商业虚拟化解决方案。
OpenVZ可以在单个物理服务器上创建多个隔离的虚拟专用服务器(VPS)并以最大效率共享硬件和管理资源。每个VPS的运行和独立服务器完全一致,因其自身的用户、应用程序都可以独立重启,它拥有根访问权限、用户、IP地址、内存、处理器、文件、应用服务、系统库文件和配置文件等。拥有轻量级处理损耗和高效设计的OpenVZ是运行应用服务和实时数据生产型服务器虚拟化的最佳选择。
OpenVZ软件同时为用户提供工具,协助自动化管理虚拟服务器。基于模板的应用程序部署可以在几分钟内用简单的方法创建新的虚拟服务器并投入使用,而且与其他的虚拟化技术相比,OpenVZ可以在每CPU上运行几倍于其他虚拟化服务器技术的虚拟化服务器。
OpenVZ是基于Linux内核和作业系统的操作系统级虚拟化技术。OpenVZ允许物理服务器运行多个操作系统,被称虚拟专用服务器(VPS,Virtual Private Server)或虚拟环境(VE, Virtual Environment)。
与硬件虚拟化的VMware和半虚拟化的Xen相比,OpenVZ的host OS和guest OS都必需是Linux(虽然在不同的虚拟环境里可以用不同的Linux发行版)。但是,OpenVZ声称这样做有性能上的优势。根据OpenVZ网站的说法,使用OpenVZ与使用独立的服务器相比,性能只会有1-3%的损失。
2006: Process Containers
Process Containers横空出世,这个名字可能比较陌生,但是提到另外一个名字:Cgroups你可能就了然了。Cgroups在容器中控制容器的资源配额,是极其重要的一个控制功能,由谷歌工程师在2006年发布,2008年在2.6.24版本合并到Linux内核中。
2008: LXC
终于,在2008年,LXC横空出世,LXC作为集大成者,采集众家之所长,有了前期的N多铺垫,终于有了容器技术的雏形。LXC的主要两大依托就是namespace和Cgroups,一个做资源隔离,解决进程可以用什么资源的问题;一个做资源控制,解决进程可以用多少资源的问题。
进程在运行时,除了CPU和内存外,其实还需要很多其他资源,为了将其隔离,需要将资源一并隔离,如网络、文件系统、IPC等,什么是namespace?
text
A namespace wraps a global system resource in an abstraction that makes it
appear to the processes within the namespace that they have their own isolated
instance of the global resource. Changes to the global resource are visible
to other processes that are members of the namespace, but are invisible to other
processes. One use of namespaces is to implement containers.
namespace的存在,使得每个进程都以为自己是单独的存在,拥有独享的必要资源,其实是被划分到一个单独的隔离区域。
2011: Warden
LXC是个好东西,加上Linux系统的覆盖面和应用广泛的加持,CloudFoundry在2011年启动了Warden项目,早期使用了LXC的技术,但是后面就用自己的实现替代掉了,它可以隔离进程的上下文环境,并且在后台提供了一个daemon进程提供了各种API来供你进行容器的管理,它提供了一种C/S架构的工具用来跨域多个主机来管理容器,它支持对cgroups,namespace及进程生命周期的管理。这是不是有Docker的影子了?如果你对Docker比较熟悉的话,和Docker的架构有点像。
2013: LMCTFY
Let Me Contain That For You (LMCTFY),谷歌在2013年搞起的一个容器栈,可以为Linux应用提供容器(container)。这些容器可以让一台机器上的不同应用使用相互隔离的资源,以独占的方式运行在同一台机器上。这些应用也可以拥有容器,因此能够创建和管理属于他们自己的子容器。这个项目的地址如下:
text
https://github.com/google/lmctfy
谷歌后来转向了libcontainer,因此这个项目在2015年停止更新,现在已经合并到了https://github.com/opencontainers/runc/tree/master/libcontainer
读到这里,感觉是不是越来越像Docker了?
2013: Docker
是的,Docker(go语言开发)也很快出现了,Docker优秀的设计使得它非常流行,像Warden一样,初期也是基于LXC的,后来就以自己的libcontainer来替代了,Docker之所以如此流行,一个重要的原因就是提供了一个完整的解决方案生态系统,使得易用、简单,这是它的前辈们所做不到的,历史上的解决方案看起来都有Docker的影子,但是都有各种各样的不足,Docker几乎解决了所有的痛点,变得非常易用。
2014 微服务
明明讲容器技术的发展史,为什么提到微服务呢?这是有原因的,大家对微服务的一致性认知,都是出自2014年,马丁福勒的那篇布道文,通俗易懂的阐述了什么是微服务架构。
其实微服务的概念早在2012年就陆续的出现了,但是由于容器技术还不太完善,微服务的一个特点就是拆分,服务的数量会增长,膨胀的服务如何部署是个问题,无论是用虚拟机还是物理机,成本都比较高,而且扩容也不是很流畅。容器技术逐渐完善了后,微服务的发展终于得到了解放,一个个小而美的服务运行在容器里,具有必要的隔离性,且近乎原生系统的性能(直接在内核上运行),简直是再合适不过了。微服务得到了长足的进展,而这又反过来促进了容器的发展。
2014 k8s
Docker引爆了容器技术,加上微服务的加持,使得二者发展迅速,但是容器更像是一个好玩的玩具,如何在产线上工业化的使用起来?网络问题、负载均衡问题、监控、部署、更新、镜像管理、发布......需要解决很多很多问题,因此容器的编排应运而生,k8s在2014年横空出世,说横空出世或许有点夸张,因为它是基于谷歌内部建设了十几年的Borg构建的开源版本,实践出真知,因此很快就成为容器编排事实上的标准。
2014: Rocket
Rocket代码: https://github.com/coreos/rkt
Rocket ( 也叫rkt,Go语言实现 ) 是一个类似Docker的命令行工具。她可以打包应用和依赖包到可移植容器中,简化搭环境等部署工作。
Rocket 的开发者认为,现在的Docker社区背离了当初设计Docker的初衷:即一个可复用的标准Linux容器。
Rocket设计目标就是希望再次实现这个初衷, 当然,它也兼容Docker(rkt可以执行 Docker镜像)。
"Rocket 和 Docker 不同的地方在于,Rocket 没有 Docker 那些为企业用户提供的"友好功能",比如云服务加速工具、集群系统等。反过来说,Rocket 想做的,是一个更纯粹的业界标准。"
CoreOS发布并开始支持rkt(最初作为Rocket发布)作为Docker的替代品。
2015 CNCF
容器技术,容器编排,微服务,三者相辅相成,共同促进,迅速发展,容器云的概念也应运而生,于是乎,谷歌在2015年底拉着一票巨头成立了CNCF这个组织,共同做大云原生这个生态,无利不起早,也是为了照顾自家生意。
如今
微服务、容器编排、容器云,整个生态变得异常的火爆
容器和虚拟机对比
Docker 和传统虚拟化方式的不同之处,容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级别 |
硬盘使用 | 一般为MB | GB |
性能 | 接近原生 | 弱 |
系统支持量 | 单机支持上千个容器 | 一般为十几个 |
Docker的发展历史
2010 年,几个搞 IT 的年轻人,在美国旧金山成立了一家名叫 dotCloud
的公司。dotCloud 的平台即服务(Platform-as-a-Service, PaaS)提供商。底层技术上,dotCloud 平台利用了 Linux 的 LXC 容器技术。
为了方便创建和管理这些容器,dotCloud 基于 Google 公司推出的 Go 语言开发了一套内部工具,之后被命名为 Docker
。Docker 就是这样诞生的。
提示:"Docker"一词来自英国口语,意为码头工人(Dock Worker),即从船上装卸货物的人。
LXC 是 Docker 的底层基石,但是在 Docker 0.9 版本的时候,Docker 见异思迁了,引入了基于 Go 语言构建的 Libcontainer 的 execution driver。有了 Libcontainer 这个项目,Docker 不再需要依赖于 Linux 部件(LXC,libvirt,systemd-nspawn...)就可以处理 namespaces、control groups、capabilities、apparmor profiles、network interfaces。这下,LXC 沦为可选项。
在 Docker 1.8 中 LXC 被 deprecated,
在 Docker 1.10,LXC 彻底出局
。Docker 推出 Libcontainer 自己集成了 Linux 内核中的很多特性,作为一个独特、稳定且不受制于 Linux 的 Library,独立的时代终于到来了。
如同 Docker 的 Logo 一样,Docker 的思想来源于集装箱。集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来,并且各种各样的货物被集装箱标准化,集装箱与集装箱之间互不影响。那么就不需要专门运送水果的船和专门运送化学用品的船了。只要这些货物封装在不同的集装箱里,就可以用一艘大船把它们都运走。
2013年,dotCloud 的 PaaS 业务并不景气,公司需要寻求新的突破。
2013 年 3 月,dotCloud 公司的创始人之一,Docker 之父,28 岁的 「Solomon Hykes」 正式决定,将 Docker 项目开源。
怀揣着"将 Docker 和容器技术推向全世界"的使命,开启了一段新的征程。
开源之后,越来越多的 IT 工程师发现了 Docker 的优点,然后蜂拥而至,加入 Docker 开源社区。Docker 的人气迅速攀升,速度之快,令人瞠目结舌。
此时的 Docker,已经成为行业里人气最火爆的开源技术,没有之一。
于是他们聘请了 Ben Golub 作为新的 CEO,将公司重命名为"Docker",放弃dotCloud PaaS 平台。
Docker架构
图片来源于docker官方文档
客户端
平常我们使用的就是客户端,通过客户端命令
和Docker引擎进行交互
Docker 是一个客户端-服务器(C/S)架构程序。
Docker 客户端只需要向 Docker 服务端发起请求,服务端将完成所有的工作并返回相应结果。
Docker 提供了一个命令行工具 docker
以及一整套 RESTful API。
比如:
shell
docker pull
docker run
服务端
Docker服务端 又称为Docker主机,Docker引擎,Docker守护进程。
依托于宿主机
,守护进程,用于管理镜像,容器,执行客户端命令等。
仓库Registry
Docker有两个重要的概念镜像
和容器
。
镜像可以理解为就是软件安装包,容器就是软件安装完成后可运行的状态。
既然镜像是软件安装包,那么这个安装包从哪下载呢?
Docker推出了Registry
这个概念,一般有人也称为是 注册中心,当我们需要发布Docker镜像(Docker专用软件安装包)的时候,就需要将镜像发布到注册中心上,这样其他人就可以下载使用。
Registry 分为公共
和私有
两种。Docker 公司运营公共的 Registry 叫做 Docker Hub
,地址为:https://hub.docker.com
- 一个 Docker Registry 中可以包含多个仓库(Repository)
- 每个仓库可以包含多个标签(Tag)
- 每个标签对应一个镜像
通常,一个仓库会包含同一个软件不同版本的镜像,而标签对应该软件的各个版本。我们可以通过 「<仓库名>:<标签>」 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 「latest」 作为默认标签。
镜像docker镜像类似于软件安装包,但和我们理解意义上是不一样的,一个dockr镜像是一个完整的操作系统描述,它描述了需要运行的程序以及运行程序所处的操作系统。镜像是一个可执行的包,其中包括运行程序所需的所有内容,包含代码,运行时间,库,环境变量和配置文件等。真正运行,需要通过镜像启动容器。容器才是真正可运行的操作系统。容器镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态定义,容器是镜像运行时的实体容器可以被创建,启动,停止,删除,暂停。未完待续
Docker重要的概念
镜像
Docker镜像是一个完整的操作系统的描述,描述了需要运行的程序以及运行程序所处的操作系统
那不同的镜像区别在哪里呢?镜像中的操作系统中安装的软件不同,运行的程序不同。
当然镜像只是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。
真正运行,我们需要通过镜像启动容器
。
容器才是真正的可运行的操作系统。
Docker 把 App 文件打包成为一个镜像,并且采用类似多次快照的存储技术,可以实现:
- 多个 App 可以共用相同的底层镜像(初始的操作系统镜像);
- App 运行时的 IO 操作和镜像文件隔离;
- 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个 App 镜像可以用来运行无数个不同业务的容器。
容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。
容器可以被创建、启动、停止、删除、暂停等。
注意:容器运行需要指定镜像,当容器运行后,一个容器就相当于一个虚拟的完整的操作系统,比如你通过mysql的镜像来安装mysql,当mysql的容器启动后,就相当于开启了一个操作系统,mysql只是安装在此容器内部的操作系统中,我们可以进入容器内部操作mysql(和正常操作系统一致),也可以通过docker命令来操作
总结
Docker是容器化的标准化实现,提供了在一个称为·容器·的松散隔离环境中打包和运行应用程序的能力。隔离和安全性可以在给定的主机上同时运行多个容器。容器是轻量级的,包含运行应用程序所需的一切,因此您不需要依赖于主机上安装的内容。您可以在工作时共享容器,并确保与您共享的每个人都获得以相同方式工作的相同容器。