共计 3174 个字符,预计需要花费 8 分钟才能阅读完成。
文言 Docker 外围原理
Docker 是什么?
「Docker 应用 Google 公司推出的 Go 语言进行开发实现,基于操作系统内核中 Cgroup(资源管制)、Namespace(资源隔离) 与 OverlayFS(数据存储)等技术,实现了基于操作系统层面的虚拟化技术。」
了解的早就了解了这句话外围实质,不了解的给他这么一解释还是云里雾里。那咱们先不急于搞懂 Docker 是什么,说到 Docker 容器,就不得不说下虚拟机 (Virtual Machine),Docker 容器和虚拟机又有什么区别呢?
Docker vs 虚拟机
虚拟机对于咱们开发者是个再相熟不过的概念,比方咱们常常应用 VMware Workstation 搭建虚构操作系统部署利用,应用 JVM 虚拟机运行 Java 利用等,如下图,「通常应用虚拟机管理器作为两头转换层,能够屏蔽底层操作系统或硬件设施差别」,比方下层虚拟机操作系统 (Guest OS) 执行程序或 Java 程序运行等,「这个中间件转换层就像翻译家一样,将下层执行的指令解释翻译成上层操作系统对应的指令进行执行」。
正如 Java 世界中吹牛的 ” 一次编译,到处运行 ”,「虚拟机实质上通过中间件转换层屏蔽了底层差别,模拟出一个新环境,实现与平台无关,达到与外界隔离的目标,这就是虚拟机实现虚拟化的核心思想」。
从虚拟机架构实现上能够看出,其存在一个很大问题:所有的指令都必须通过虚拟机管理器这个两头转换层翻译解释能力在实在操作系统上运行,这就意味着虚构机会存在性能损耗。另外,为了模仿一个 Linux 环境上运行的利用,须要应用 VMware 运行部署一个宿主机 (Guest OS),再在宿主机上运行利用,宿主机自身占用好几个 G 的存储空间、400-500MB+ 内存空间,当初微服务架构动不动就是 10+、100+ 个利用组件须要部署,那这些组件都须要做隔离部署应用虚拟机形式无疑是致命的。
上述说的虚拟机存在性能问题和资源节约造成了虚拟机对细粒度的环境隔离有点力不从心,而这又与以后风行的微服务架构场景下,零碎被拆分成几十、上百个微服务利用组件须要独立部署存在抵触。Docker 推崇的是一种轻量级容器的构造,即一个利用一个容器。所以,Docker 一进去就被推向巅峰,那它又是如何搞定虚拟机隔离存在的问题的呢?
Docker 容器核心技术
Docker 容器中过程是间接运行在底层操作系统上,没有两头转换层,所以也就不存在性能损耗的问题。要害那它是如何做到隔离的呢?
「这里就引出了撑持 Docker 容器的两大内核技术:Namespace 和 Cgroups(Control Groups)」。Namespace 次要是用来进行「资源隔离」,对于那些计算型资源,比方 CPU、内存、磁盘 IO 等不能进行隔离的资源,这时就须要采纳 Cgroups 进行「资源限度」,避免有些资源耗费较大的容器,将整个物理机器的硬件资源 (CPU, Memory、磁盘 IO 等) 占满,进而影响其它过程性能。
Namespace 和 Cgroups 这两个技术都是 Linux 内核自身反对的性能,Docker 如果只应用这两大技术也不可能造就出道即巅峰的炽热水平,Docker 翻新点恰好是引入镜像概念,并应用联结文件系统(UnionFS) 技术很好的实现了镜像分层,这样就能够将利用部署介质、依赖环境配置文件以及操作系统二进制文件进行分层叠加构建出利用运行时文件系统环境。
镜像蕴含一个根底镜像 (Base Image),这个个别蕴含操作系统介质,比方 centos、debian,然而它只包含应用的操作系统二进制文件,并没有包含内核相干,所以,它的体积远远小于部署整个操作系统占用的空间,比方一个 centos 根底镜像大略只有 70-80MB。另外,镜像分层设计进一步缩小存储占用,比方当初 100+ 利用组件都是基于 centos 根底镜像部署,理论部署时只须要拉取一份 centos 根底镜像,就像搭积木一样,将每一层应用的文件进行组合叠加,最终构建出程序运行时残缺的目录构造。
文言核心技术关系
「Docker 容器技术炽热的背地,其实是 Namespace、Cgroups 和 UnionFS 三大技术创新的联合,造就出了 Docker 这种景象级产品」。上面用个比拟形象的比喻来帮忙你了解三大技术关系:
1、失常程序启动时间接运行在操作系统上,应用 Docker 启动程序时,也是间接运行在操作系统上,然而 Docker 引擎在启动程序时会给程序套一个立方体壳(见下图);
2、这个立方体壳前后左右四个面应用 Namespace 资源隔离技术打造,这样就给 Docker 容器中过程和其它过程隔离开来,给容器中过程造成一种运行在一个独立环境中的假象(见下图);
3、这个立方体壳的下面这个面应用 Cgroups 资源限度技术打造,防止程序壮大成长进去抢占其它过程的资源,进而影响其它过程性能,这样就给盖盖上加上了一个紧箍咒,再牛逼的程序也会把你死死的限制住(见下图);
4、最初再来看下这个立方体壳剩下的最上面这个面,其采纳 UnionFS 技术打造,构建出容器中过程运行时文件系统根基。将操作系统二进制指令、依赖配置文件、程序介质等通过镜像分层叠加构建出程序运行时看到的整个文件系统环境;比方宿主机是 Debian 零碎,然而根底镜像是 CentOS 环境,容器中过程看到的是 CentOS 零碎,而不是 Debian 零碎,同时将 yum install 装置的依赖介质也通过镜像打包进来,容器中过程就不须要关注宿主机上到底有没有装置该依赖介质等等,这样容器中过程看到是一个领有程序运行时残缺介质,并与宿主机操作系统隔离开的独立操作系统(见下图);
5、所以,程序运行在三大核心技术发明的立方体壳壳中,被蒙蔽双眼傻乎乎的认为运行在一个独立计算机环境中,看不到外界程序运行状况,也影响不到外界程序的运行。
如何查看 Docker 过程在宿主机上的 PID?
Docker 容器中的过程是间接运行在宿主机上,能够通过 docker inspect container 查看到 Docker 容器中过程在宿主机上对应的 PID 信息(见下图):
宿主机上 ps -ef 查看下容器过程信息:
因为,这里运行的是一个 nginx 容器,所以宿主机上看到对应的是 nginx 主过程,同时该过程创立了两个 nginx worker 子过程。
Docker 容器缺点
「高性能、轻便是容器相较于虚拟机最大的劣势,容器实质上是一种非凡的过程。」
不过,无利就有弊,基于 Namespace 的资源隔离和 Cgroups 的资源限度都不是那么彻底,因为容器之间底层还是共享应用宿主机的 Linux 内核,只管你能够在容器里应用不同版本的操作系统文件,比方 CentOS 或者 Ubuntu,但这并不能扭转共享宿主机内核的事实。这意味着,如果你要在 Windows 宿主机上运行 Linux 容器,或者在低版本的 Linux 宿主机上运行高版本的 Linux 容器,都是行不通的。
其次,在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,最典型的例子就是:工夫。这就意味着,如果你的容器中的程序修改了工夫,整个宿主机的工夫都会被随之批改,这显然不合乎用户的预期。
另外,跟 Namespace 的状况相似,Cgroups 对资源的限度能力也有很多不欠缺的中央,这里最常见的是 /proc 文件系统的问题。Linux 下的 /proc 目录存储的是记录以后内核运行状态的一系列非凡文件,用户能够通过拜访这些文件,查看零碎以及以后正在运行的过程的信息,比方 CPU 应用状况、内存占用率等,这些文件也是 top 指令查看零碎信息的次要数据起源。然而,你如果在容器里执行 top 指令,就会发现,它显示的信息竟然是宿主机的 CPU 和内存数据,而不是以后容器的数据。造成这个问题的起因就是,Docker 引擎在启动过程时间接将宿主机 /proc 下很多文件挂载到 Docker 容器上。