一、解决的问题
由于不同的机器有不同的操作系统,以及不同的库和组件,在将一个应用部署到多台机器上需要进行大量的环境配置操作。
docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 docker 可以不修改应用程序代码,不需要开发人员学习特定环境下的技术,就能够将现有的应用程序部署在其它机器上。
二、与虚拟机的比较
虚拟机也是一种虚拟化技术,它与 docker 最大的区别在于它是通过模拟硬件,并在硬件上安装操作系统来实现。
比较两图的差异,左图虚拟机的guest os层和hypervisor层在docker中被docker engine层所替代。虚拟机的guest os即为虚拟机安装的操作系统,它是一个完整操作系统内核;虚拟机的hypervisor层可以简单理解为一个硬件虚拟化平台,它在host os是以内核态的驱动存在的。
虚拟机实现资源隔离的方法是利用独立的os,并利用hypervisor虚拟化cpu、内存、io设备等实现的。例如,为了虚拟cpu,hypervisor会为每个虚拟的cpu创建一个数据结构,模拟cpu的全部寄存器的值,在适当的时候跟踪并修改这些值。需要指出的是在大多数情况下,虚拟机软件代码是直接跑在硬件上的,而不需要hypervisor介入。只有在一些权限高的请求下,guest os需要运行内核态修改cpu的寄存器数据,hypervisor会介入,修改并维护虚拟的cpu状态。
hypervisor虚拟化内存的方法是创建一个shadow page table。正常的情况下,一个page table可以用来实现从虚拟内存到物理内存的翻译。在虚拟化的情况下,由于所谓的物理内存仍然是虚拟的,因此shadow page table就要做到:虚拟内存->虚拟的物理内存->真正的物理内存。
对于io设备虚拟化,当hypervisor接到page fault,并发现实际上虚拟的物理内存地址对应的是一个i/o设备,hypervisor就用软件模拟这个设备的工作情况,并返回。比如当cpu想要写磁盘时,hypervisor就把相应的数据写到一个host os的文件上,这个文件实际上就模拟了虚拟的磁盘。
对比虚拟机实现资源和环境隔离的方案,docker就显得简练很多。docker engine可以简单看成对linux的namespace、cgroup、镜像管理文件系统操作的封装。docker并没有和虚拟机一样利用一个完全独立的guest os实现环境隔离,它利用的是目前linux内核本身支持的容器方式实现资源和环境隔离。简单的说,docker利用namespace实现系统环境的隔离;利用cgroup实现资源限制;利用镜像实现根目录环境的隔离。
总结一下:
- 从虚拟化层面来看,传统虚拟化技术是对硬件资源的虚拟,容器技术则是对进程的虚拟,从而可提供更轻量 级的虚拟化,实现进程和资源的隔离。
- 从架构来看,docker比虚拟化少了两层,取消了hypervisor层和guestos层,使用 docker engine 进行调度和隔离
三、优劣势和应用场景
优势
1. 启动速度快
启动虚拟机需要先启动虚拟机的操作系统,再启动应用,这个过程非常慢;
而启动 docker 相当于启动宿主操作系统上的一个进程。
2. 占用资源少
虚拟机是一个完整的操作系统,需要占用大量的磁盘、内存和 cpu 资源,一台机器只能开启几十个的虚拟机。
而 docker 只是一个进程,只需要将应用以及相关的组件打包,在运行时占用很少的资源,一台机器可以开启成千上万个 docker。
3. 更容易迁移
提供一致性的运行环境。直接迁移到不同机器,而不用担心环境
4. 更容易维护
使用分层技术和镜像,使得应用更容易复用
5. 更容易扩展
可以使用基础镜像进一步扩展得到新的镜像,并且官方和开源社区提供了大量的镜像,通过扩展这些镜像可以非常容易得到我们想要的镜像。
劣势
1.资源隔离方面不如虚拟机,docker是利用cgroup实现资源限制的,只能限制资源消耗的最大值,而不能隔绝其他程序占用自己的资源。
2.安全性问题。docker目前并不能分辨具体执行指令的用户,只要一个用户拥有执行docker的权限,那么他就可以对docker的容器进行所有操作,不管该容器是否是由该用户创建。
3. docker目前还在版本的快速更新中,不够稳定
应用场景
1. 持续集成
持续集成指的是频繁地将代码集成到主干上,这样能够更快地发现错误。
docker 具有轻量级以及隔离性的特点,在将代码集成到一个 docker 中不会对其它 docker 产生影响。
2. 提供可伸缩的云服务
根据应用的负载情况,可以很容易地增加或者减少 docker。
3. 搭建微服务架构
docker 轻量级的特点使得它很适合用于部署、维护、组合微服务。
四、镜像与容器
镜像是一种静态的结构,可以看成面向对象里面的类,而容器是镜像的一个实例。
镜像包含着容器运行时所需要的代码以及其它组件,它是一种分层结构,每一层都是只读的(read-only layers)。构建镜像时,会一层一层构建,前一层是后一层的基础。镜像的这种分层存储结构很适合镜像的复用以及定制。
构建容器时,通过在镜像的基础上添加一个可写层(writable layer),用来保存着容器运行过程中的修改。