iAfoot(4780) Docker简介

208 阅读15分钟

Docker的历史和发展

2013年初一个叫dotCloud的PaaS服务提供商将一个内部项目Docker开源

对于Docker,目前的定义是一个开源的容器引擎,可以方便地对容器(关于容器,将在第2章详细介绍)进行管理。其对镜像的打包封装,以及引入Docker Registry对镜像的统一管理,构建了方便快捷的“Build,Ship and Run”流程,它可以统一整个开发、测试和部署的环境和流程,极大地减少运维成本。另外,得益于容器技术带来的轻量级虚拟化,以及Docker在分层镜像应用上的创新,Docker在磁盘占用、性能和效率方面相较于传统的虚拟化都有非常明显的提高

目前Docker已加入Linux基金会,遵循Apache 2.0协议,其代码托管于[Github]( github.com/docker/dock… )。

Docker的架构介绍

要了解Docker,首先要看看它的架构图,如图1-1所示。

从图1-1可知,Docker并没有传统虚拟化中的Hypervisor层因为Docker是基于容器技术的轻量级虚拟化,相对于传统的虚拟化技术,省去了Hypervisor层的开销,而且其虚拟化技术是基于内核的Cgroup和Namespace技术,处理逻辑与内核深度融合

在通信上,Docker并不会直接与内核交互,它是通过一个更底层的工具Libcontainer与内核交互的Libcontainer是真正意义上的容器引擎,它通过clone系统调用直接创建容器,通过pivot_root系统调用进入容器,且通过直接操作cgroupfs文件实现对资源的管控,而Docker本身则侧重于处理更上层的业务

Docker的另一个优势是对层级镜像的创新应用,即不同的容器可以共享底层的只读镜像通过写入自己特有的内容后天就新的镜像层,新增的镜像层和下层镜像一起又可以作为基础镜像被更上层的镜像使用。这种特性可以极大地提高磁盘利用率,所以当你的系统上有10个大小为1GB的镜像时,它们总共占用的空间大小可能只有5GB,甚至更少。另外**,Docker对Unio mount的应用还体现在多个容器使用同一个基础镜像时,可极大地减少内存占用等方面,因为不同的容器访问同一个文件,只会占用一份内存**。当然这需要使用支持Union mount的文件系统作为存储的Graph Driver,比如AUFS和Overlay。

功能和组件

Docker为实现所描述功能,引入了以下概念:

Docker客户端
Docker daemon
Docker容器
Docker镜像
Registry

Docker客户端

Docker是一个典型的C/S架构的应用程序,但在发布上,Docker将客户端和服务器端统一在同一个二进制文件中,不过,这只是对Linux系统而言的,在其他平台如Mac上,Docker只提供了客户端。

Docker客户端一般通过Docker command来发起请求,另外,也可以通过Docker提供的一整套RESTful API来发起请求,这种方式更多地被应用在应用程序的代码中

Docker daemon

Docker daemon也可以被理解成Docker Server,另外,人们也常常用Docker Engin来直接描述它,实际上就是驱动整个Docker功能的核心引擎

简单说,Docker daemon实现的功能就是接收客户端发来的请求,并实现请求所要求的功能,同时针对请求返回相应的结果。在功能的实现上,因为涉及了容器、镜像、存储等多方面的内容,daemon内部的机制会复杂很多,涉及了多个模块的实现和交互。

Docker容器

在Docker的功能和概念中,容器是一个核心内容,相对于传统虚拟化,它作为一项基础技术在性能上给Docker带来了极大优势。

在功能上,Docker通过Libcontainer实现对容器生命周期的管理、信息的设置和查询,以及监控和通信等功能。容器以镜像为基础,同时又为镜像提供了一个标准的和隔离的执行环境。

在概念上,容器很好地诠释了Docker集装箱的理念,集装箱可以存放任何货物,可以通过邮轮将货物运输到世界各地。运输集装箱的邮轮和装载卸载集装箱的码头都不用关心集装箱里的货物,这是一个标准的集装箱和运输方式。类似的,Docker的容器就是“软件界的集装箱”,它可以安装任意的软件和库文件,做任意的运行环境配置。开发和运维任意在转移和部署应用的时候,不用关心容器里装了什么软件,也不用了解他们是如何配置的。而管理容器的Docker引擎同样不关心容器里的内容,它只要像码头工人一样让这个容器运行起来就可以了,就像所有其他容器那样。

容器不是一个新的概念,但是Docker在对容器进行封装后,与集装箱的概念对应起来了,它之所以被称为“软件界的创新和革命”,是因为它会改变软件的开发、部署形态,降低成本,提高效率。Docker真正把容器推广到了全世界。

Docker镜像

与容器相对应,如果说容器提供了一个完整的、隔离的运行环境,那么镜像则是这个运行环境的静态体现,是一个还没有运行起来的“运行环境”。

相对于传统虚拟化中的ISO镜像,Docker镜像要轻量化很多它只是一个可定制的rootfs。Docker镜像的另一个创新是它是层级的并且是可复用的,这在实际应用场景中极为有用,多数基于相同发行版的镜像,在大多数文件的内容上都是一样的,基于此,当然会希望可以复用它们,而Docker做到了。在此类应用场景中,利用Unionfs的特性,Docker会极大地减少磁盘和内存的开销。

Docker镜像通常是通过Dockerfile来创建的,Dockerfile提供了镜像内容的定制,同时也体现了层级关系的建立。另外Docker镜像也可以通过使用docker commit这样的命令来手动将修改后的内容生成镜像,这些都将在后续的章节详细介绍。

Registry

Registry是一个存放镜像的仓库,它通常被部署在互联网服务器或者云端。通常,集装箱是需要通过油轮经行海洋运输到世界各地的,而互联网时代的传输则要方便很多,在镜像的传输过程中,Registry就是这个传输的重要中转站。假如我们在公司将一个软件的运行环境制作成镜像,并上传到Registry中,这时就可以很方便地在家里的笔记本上,或者在客户的生成环境上直接从Registry上下载并运行了。当然,对Registry的操作也是与Docker完美融合的,用户甚至不需要知道Registry的存在,只需要通过简单的Docker命令就可以实现上面的操作。

Docker公司提供的官方Registry叫Docker Hub,这上面提供了大多数常用软件和发行版的官方镜像,还有无数个人用户提供的个人镜像。其实,Registry本身也是一个单独的开源项目,任何人都可以下载后自己部署一个Registry。因为免费的Docker Hub功能相对简单,所以多数企业会选择自己部署Docker Registry后二次开发,或者购买功能更强大的企业版Docker Hub。

安装和使用

Docker的安装

Docker的安装和使用有一些前提条件,主要体现在体系架构和内核的支持上。对于体系架构,除了Docker一开始就支持的x86-64,其他体系架构的支持则一直在不断地完善和推进中,用户在安装前需要到Docker官方网站查看最新的支持情况。对于内核,目前官方的建议是3.10以上的版本,除了内核版本以外,Docker对内核支持的功能,即内核的配置选项也有一定的要求(比如必须开启Cgroup和Namespace相关选项,以及其他的网络和存储驱动等)。如果你使用的是主流的发行版,那通常它们都已经打开了,如果使用的是定制化的内核**,Docker源码中提供了一个检测脚本(目前的路径是./contrib/check-config.sh)来检测和指导内核的配置**。

在满足前提条件后,安装就非常的简单了,对于多数主流的发行版,通常只需要一条简单的命令即可完成安装,比如在Ubuntu下,可以使用如下命令安装

当然,实际情况可能会相对复杂些,比如,虽然Ubuntu中通常自带了Docker,但用户常常需要使用最新版本的Docker,以至于不得不对其进行升级。对于安装和升级,以及不同发行版上的操作方法,官方网站上提供了更加详细的说,本书不做过多的赘述,下面的链接给出了常用发行版的安装方法:

·[Ubuntu](docs.docker.com/installatio…
·[Fedora](docs.docker.com/installatio…
·[Debian](docs.docker.com/installatio…
·[Centos](docs.docker.com/installatio…
·[Gentoo](docs.docker.com/installatio…
·[ArchLinux](docs.docker.com/installatio…
·[Windows](docs.docker.com/installatio…
·[MacOSX](docs.docker.com/installatio…

另外,用户也可以直接获取Docker binary来运行,docs.docker.com/installatio…因为通过软件包安装的Docker,除了有可执行文件之外,还包括了Shell自动完成脚本、man手册、服务运行和配置脚本等内容,可以帮助用户更好地配置和使用Docker。

提示:

Docker还有一些其他更方便的安装方式,这将在后面的章节中详细介绍。

Docker的使用

对于初学者,官方提供的tryit是最好的快速入门途径,建议每一个初次接触Docker的用户都可以试一试。对于有一定经验的用户,在使用中遇到问题或者不确定具体的用法时,可以通过以下途径来查看帮助信息。

1)在控制台直接运行docker,这样会列出Docker支持的所有命令和一些通用的参数,如下:

2)在控制台执行“docker+命令+ --help”,比如“docker start —help”,这样会列出docker start命令支持的所有参数,如下:

3)使用man命令查看帮助文档,对于通过rpm包等方式安装的Docker,一般都会默认安装对应的man文档,此时可通过“man+docker+command”的方式查看子命令的帮助文档,比如“man docker start”,通常man手册中包含的帮助信息会更丰富一些,通过完整地阅读man手册,基本上就可以掌握该命令的常规用法。

概念澄清

Docker在LXC基础上做了什么工作

首先我们需要明确LXC的概念,但这常常有不同的认识。LXC目前代表两种含义:

这里通常指第二种,即Docker在内核容器技术的基础上做了什么工作。简单地说,Docker在内核容器技术(Cgroup和Namespace)的基础上,提供了一个更高层的控制工具,该工具包含以下特性。

  • 跨主机部署Docker定义了镜像格式,该格式会将应用程序和其所依赖的文件打包到同一个镜像文件中,从而使其在转移到任何运行Docker的机器中时都可以运行,并且能够保证在任何机器中该应用程序执行的环境都是一样的LXC实现了“进程沙盒”。这一重要特性是跨主机部署的前提条件,但是只有这一点远远不够,比如,在一个特定的LXC配置下执行应用程序,将该应用程序打包并拷贝到另一个LXC环境下,程序很有可能无法正常执行,因为该程序的执行依赖于该机器的特定配置,包括网络、存储、发新版等。而Docker则将上述相关配置进行抽象并与应用程序一同打包,所以可以保证在不同硬件、不同配置的机器上Docker容器中运行的程序和其所依赖的环境及配置是一致的。
  • 以应用为中心,Docker为简化应用程序的部署过程做了很多优化,这一目的在Docker的API、用户接口、设计哲学和用户文档中都有体现,其Dockerfile机制大大简化和规范了应用的部署方法。
  • 自动构建Docker提供了一套能够从源码自动构建镜像的工具。该工具可以灵活地使用make、maven、chef、puppet、salt、debian包、RPM和源码包等形式,将应用程序的依赖、构建工具和安装包进行打包处理,而且当前机器的配置不会影响镜像的构建过程。
  • 版本管理Docker提供了类似于Git的版本管理功能,支持追踪镜像版本、检验版本更新、提交新的版本改动和回退版本等镜像的版本信息中包括制作方式和制作者信息,因此可以从生产环境中回溯到上游开发人员。Docker同样实现了镜像的增量上传下载功能,用户可以通过获取新旧版本之间新增的镜像层来更新镜像版本,而不必下载完整镜像,类似Git中的pull命令。
  • 组件重用任何容器都可以作为生成另一个组件的基础镜像。这一过程可以手动执行,也可以写入自动化构建的脚本。例如,可以创建一个包含Python开发环境的镜像,并将其作为基础镜像部署其他使用Python环境进行开发的应用程序。
  • 共享Docker用户可以访问公共的镜像Registry,并向其中上传有用的镜像。Registry中同样包含由Docker公司维护的一些官方标准镜像。Docker Registry本身也是开源的,所以任何人都可以部署自己的Regist来存储并共享私有镜像。
  • 工具生态链。Docker定义了一系列API来定制容器的创建和部署过程并实现自动化。有很多工具能够与Docker集成并扩展Docker的能力,包括类PaaS部署工具(Dokku、Deis和Flynn)、多节点编排工具(Meastro、Salt、Mesos、OpenStack nova)、管理面板(Docker-ui、Openstack Horizon、Shipyard)、配置管理工具(Chef、Puppe)、持续集成工具(Jenkins、Strider、Travis)等。Docker正在建立以容器为基础的工具集标准。

Docker容器和虚拟机之间有什么不同

容器与虚拟机是互补的。虚拟机是用来进行硬件资源划分的完美解决方案,它利用了硬件虚拟化技术,例如VT-x、AMD-V或者privilege level(权限等级)会同时通过一个hypervisor层来实现对资源的彻底隔离;而容器则是操作系统级别的虚拟化,利用的是内核的Ggroup和Namespace特性,此功能完全通过软件来实现,仅仅是进程本身就可以与其他进程隔离开,不需要任何辅助。

Docker容器与主机共享操作系统内核,不同的容器之间可以共享部分系统资源,因此容器更加轻量级,消耗的资源也更少。而虚拟机会独占分配给自己的资源,几乎不存在资源共享,各个虚拟机实例之间近乎完全隔离,因此虚拟机更加重量级,也会消耗更多的资源。我们可以很轻松地在一台普通的Linux机器上运行100个或者更多的Docker容器,而且不会占用太多系统资源(如果容器中没有执行运行任务或I/O操作);而在单台机器上不可能创建100台虚拟机,因为每一个虚拟机实例都会占用一个完整的操作系统所需要的所有资源。另外,Docker容器启动很快,通常是秒级甚至是毫秒级启动。而虚拟机的启动虽然会快于物理机器,但是启动时间也是在数秒甚至数十秒的量级

因此,可以根据需求的不同选择相应的隔离方式。如果需要资源完全隔离并且不考虑资源消耗,可以选择使用虚拟机;而若是想隔离进程并且需要运行大量进程实例,则应该选择Docker容器。