一、什么是Docker
参考:
要理解Docker,先要理解容器的概念。操作系统层虚拟化——容器概念的提出,使所有的应用使用同一个操作系统以减少硬件资源的浪费,同时能够避免包括运行库在内的软件冲突。
容器、Type II虚拟机和物理机的区别如下。
Author:木头龙
+-----+-----+-----+-----+ +-----+-----+-----+-----+
|App A|App B|App C|App D| +-----+-----+-----+-----+ |App A|App B|App C|App D|
+-----+-----+-----+-----+ |App A|App B|App C|App D| +-----+-----+-----+-----+
|+---------------------+| +-----+-----+-----+-----+ |Guest|Guest|Guest|Guest|
|| Runtime Library || |Lib A|Lib B|Lib C|Lib D| | OS0 | OS1 | OS2 | OS3 |
|+---------------------+| +-----+-----+-----+-----+ +-----+-----+-----+-----+
|| Kernel || | Container Engine | | Hypervisor |
|+---------------------+| +-----------------------+ +-----------------------+
| Operating System | | Host OS | | Host OS |
+-----------------------+ +-----------------------+ +-----------------------+
| Hardware | | Hardware | | Hardware |
+-----------------------+ +-----------------------+ +-----------------------+
Physical Machine Container Type II Hypervisor
上方中每一个App和Lib的组合,就是一个容器。容器有能够迅速启动、占用资源少的优点。
可以看到,容器和虚拟机技术的区别在于:
- 容器使用其Container Engine技术,将应用和运行库打包,没有自己的内核和硬件虚拟;
- 而对于虚拟机技术而言,其是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程
总结:
Docker使用Go语言开发,基于Linux内核的cgroup、namespace以及OverlayFS类的Union FS技术,对进程进行封装和隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其他的隔离的进程,也称其为容器。
Docker在容器的基础之上, 进一步进行封装,从文件系统、网络互联到进程隔离,极大简化了容器的创建和维护,使得Docker技术比虚拟机技术更加轻便快捷。
二、Docker的基本概念
Docker有三个基本概念:
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
2.1 Image
Docker镜像可以类比为一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
Docker设计时利用了UnionFS技术,将其设计为分层存储的架构。所以镜像并不是像ISO一样的打包文件,其只是一个虚拟的概念,其实际体现是由多层文件系统联合组成。
镜像在构建时,会一层一层地构建,每一层发生的改变只发生在本层。
2.2 Container
镜像和容器的关系,就像面向对象编程中类和对象的关系。容器的实质是进程,容器进程运行于属于自己独立的命名空间,因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。
每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,称这个为容器运行时读写而准备的存储层为容器存储层。容器消亡时,容器存储层也随之消亡。
容器存储层需要保持无状态化,容器不应该向存储层存入任何数据,所有的文件写入操作,应该使用数据卷,或者绑定宿主目录,对这些位置的文件进行读写会跳过容器存储层,直接对宿主发生读写,其性能和稳定性更高。而数据卷的生命周期独立于容器。
2.3 Repository
Docker Registry是一个集中存储、分发镜像的服务。一个Docker Registry可以包含多个仓库Repository;每个仓库Repository可以包含多个标签Tag。
一个仓库通常会包含同一个软件不同版本的镜像,标签就对应于该软件的各个版本,可以通过 <仓库名>:<标签> 来指定软件版本,如果不给定标签,那么就将latest作为默认标签。