什么是Docker?
Docker是一种操作系统层面的虚拟化技术。
Docker通过对容器的进一步封装,从文件系统,网络互联到进程隔离等等,极大的简化了容器的创建和维护。
这里的容器指的是通过namespace,cgroup,overlay file system技术隔离出来的进程。
Docker相比于传统的虚拟机技术有什么优势?
传统虚拟机采用的技术是虚拟出一套硬件后,在虚拟出来的硬件上运行一个完整的操作系统,然后在这个系统上运行所需要的应用进程;
而Docker是直接运行在宿主机器的内核上,容器并没有自己的内核,而且也没有硬件虚拟,所以Docker相比于传统虚拟机技术更加的轻便。
为什么要用Docker?
或者我们可以理解为Docker相比于传统虚拟机有什么优势
- 更高效的利用资源
- 更快速的启动时间
- 一致的运行环境
- 持续交付和部署
- 更轻松的迁移
- 更轻松的维护和扩展
基本概念
Docker中有三个重要的基本概念
- 镜像
- 容器
- 仓库
Docker镜像
操作系统分为内核和用户空间。在linux中当内核启动之后,通常会挂载一个root文件系统为其提供用户空间的支持。而我们的Docker镜像其实就相当于一个root文件系统。
1.内核空间和用户空间
对32位操作系统而言,它的寻址空间(虚拟地址空间,或叫做线性地址空间)为4G(2的32次方)。也就是说一个进程的最大地址空间为4G。操作系统的核心是内核,它独立于普通的应用程序,运行在内核空间。而用户空间就是普通的应用程序运行的空间。为了安全考虑,这两个空间是相互隔离的,这样也就保证了用户程序崩溃了,对内核也是没有影响的。所以操作系统区分内核态和用户态的本质是为了提高操作系统的稳定性及可用性。
内核空间可以执行任何命令,调用系统的一切资源;用户空间只能执行简单的运算,不能直接调用系统资源,必须通过系统接口,才能向内核发出指令。
在这里引入一个概念,Inter将CPU的特权等级定位4个:Ring0~Ring3。在Linux中使用的是Ring0和Ring3这两个特权等级,当进程运行在Ring3的时候表示运行在用户态,当进程运行在Ring0的时候表示运行在内核态。
2.root文件系统
root文件系统首先是一种文件系统,但是对于普通的文件系统来说,它的特殊之处在于,他是内核启动之后第一个挂载的文件系统,内核代码的映像文件保存在根文件系统中。根文件系统之所以称为根文件系统,因为它是其他文件系统的根,既然是根的话。如果没有这个根,那么其他的文件系统也就无法进行加载的。
Docker镜像虽然说相当于一个root文件系统,但是还是有点区别的,它除了提供容器运行时所需要的程序、库、资源、配置等文件外,还包含了一些为运行时准备的配置参数。
3.分层存储
因为我们的Docker镜像中包含着一个完整root文件系统,这个体积是非常大的,所以在Docker设计的时候采用了Union File System的技术,将其设计成一种分层存储的架构。所以严格的说镜像并不是一个文件或者一个包,镜像是一个虚拟的概念,具体实现是由一组文件系统组成,或者说是由多层的文件系统组成。
在镜像构建的时候,是一层一层的构建,前一层是后一层的基础。每一层构建完成之后就不会发生变化了。后一层上的任何改变只发生在自己这一层。比如删除前一层文件的操作,只是会在当前这一层做一个标记,而不是去真正删除前一层文件。最终在容器运行的时候,虽然看不见上一层的文件,但是上一层的文件会一直跟随镜像的。
Docker容器
镜像(Image)和容器(Container)的关系就好像面向对象中类和实例的关系一样,镜像是一个静态的定义,容器是镜像运行时的定义。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是一个进程,但是与在宿主机器上直接运行的进程还是有所区别的。容器的进程运行于自己独立的命名空间。所以他可以拥有自己的root文件系统,自己的网络配置,自己的进程空间,甚至与自己的用户ID空间。
所以我们在使用的时候就好像在一个独立于宿主的系统下运行的一样。
容器的存储方式和镜像一样都是采用分层存储的,容器以镜像为基础,在其上再构建了一个当前容器的存储层,作为容器运行时读取的存储层。
由于存储层的生命周期和容器是一样的,随着容器的消亡而消亡,所以保存在存储层中的数据会随着容器的销毁而销毁,所以容器不应该向存储层写入任何数据,保证存储层的无状态化。而所有的文件写入都需要通过数据卷、或者绑定宿主机器目录,这样跳过了存储层,直接对宿主机器进行读写,保证了性能和稳定性。
数据卷独立于容器,不会随着容器的消亡而消亡。
Docker Registry
一个Docker镜像构建完成之后,很容易的就可以在当前宿主机器上运行。但是,如果需要在其他机器上也运行这个镜像,我们就需要一个统一管理的地方,这个就是Docker Registry。
一个Docker Registry中可以包含多个仓库,一个仓库中可以包含多个标签,一个标签代表着一个镜像。
一般来说,一个仓库中保存的都是同一个软件的不同版本的镜像,标签则用来区别版本,我们通过<仓库名>:<标签>来指定具体是哪个版本的镜像。
Registry有公有Docker Hub,同时也可以搭建自己的私有Registry。