docker(二)初识 docker
在第一章的容器化架构中,我们已经了解到了 docker 是一个容器化技术,本章将详细介绍什么是虚拟化、容器化技术,以及什么是 docker。
一、物理机 VS 虚拟化 VS 容器化
物理机:
实际的服务器或者计算机。是相对于虚拟机而言的对实体计算机的称呼。物理机负责给虚拟机提供硬件环境,有时也称为“寄主”或“宿主”。
虚拟化:
指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个虚拟机,每个虚拟机可运行不同的操作系统(每一个虚拟机都可以视作有自己的 CPU、内存、操作系统等),并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
容器化:
容器化是虚拟化技术的一种,又称操作系统层虚拟化,只虚拟化了OS层面而没有虚拟化硬件层面,硬件仍是共享。docker 是现今容器化技术的事实标准。
容器化技术实际上是让一个操作系统上的用户空间被分割成多个独立的部分,每个部分都可以运行自己的应用和服务。这就好像在同一台服务器上同时运行多个虚拟的“小服务器”,每个“小服务器”就是一个容器。对于使用这些容器的人来说,他们操作的程序就像是在自己专用的服务器上运行一样,彼此之间不会干扰。这样做的好处是可以更高效地利用资源,并且让应用程序的部署和管理变得更加简单。
生活化的小例子
物理机:就像一个庄园,独立占用了一块土地,庄园都是自己的,其他人无法共享使用。
虚拟机:相当于开发商的一个楼盘,一栋楼一套房子一户人家,共享一块宅基地,共享小区的花园,共享小区的游乐设施等。
容器:相当于在 1 个房子里面,开辟出来一个又一个的胶囊公寓,共享这套房子的卫生间、共享厨房、共享 WiFi,只有衣服、电脑等私人物品是你自己的
为什么要存在虚拟化和容器化?
虚拟化和容器化最开始的目的就是实现资源隔离,但是随着资源隔离的实现,同时也带来了其它更大的收益。
1、资源利用率高
可以对原本利用率较低的服务器资源进行整合,用更少硬件资源运行更多的业务,降低 IT 支出和
运维管理成本。
就类似对土地直接复用,使用这块土地的人多了,但是成本还是庄园那块地。
2、环境标准化
一次构建,随处执行。实现执行环境的标准化发布,部署和运维。
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 可能并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
3、实现资源弹性伸缩
可以根据业务情况,动态调整计算、存储、网络等硬件及软件资源。比如遇到双 11 了,可以把服务扩容 100 个,双 11 过去了, 把扩容的 100 个收回去。
4、提供差异化环境
可以同时提供多套差异化的执行环境,并限制环境使用资源。
比如我的服务一个以来 Ubuntu 操作系统,一个服务依赖 CentOS 操作系统,但是没有预算购买两个物理机,这个时候容器化就能很好的提供多种不同的环境。
5、沙箱安全
为了避免不安全或不稳定软件对系统安全性和稳定性造成影响,可使用虚拟化技术构建虚拟执行环境。
比如我在容器里面执行 rm -rf /* 不会把整个服务器搞死,也不会影响其他人部署的程序使用。
6、相比于虚拟机,容器更轻量,启动更快
传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 不需要为每个容器创建一个完整的操作系统实例,直接使用宿主机(即运行 Docker 的那台机器)的操作系统内核,在同一个内核上运行多个隔离的用户空间实例(即容器)。
由于容器共享宿主机的内核,它们比虚拟机启动更快、占用资源更少,因为虚拟机需要运行一整个操作系统,包括内核在内的所有组件。
通过这种方式,Docker 实现了应用的高效部署和运行,同时保持了不同容器之间的隔离性;因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
docker 不需要虚拟内核,所以启动可以更快,相当于省去了 windows 的开机时间。
7、更易于维护和扩展
Docker 使用的分层存储以及镜像的技术(后文都会介绍),使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。
此外,Docker 团队还和各个开源项目团队一起维护了一大批高质量的官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
比如 docker hub 提供了很多镜像,各个系统的一个命令就可以拿到了,研发也可以自己定制镜像分享给各个产品。
虚拟化技术的常见类别
1、虚拟机
存在于硬件层和操作系统层间的虚拟化技术。虚拟机通过“伪造”一个硬件抽象接口,将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样的功能。
比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台电脑打开 Android 系统上的应用。
2、容器
存在于操作系统层和函数库层之间的虚拟化技术。容器通过“伪造”操作系统的接口,将函数库层以上的功能置于操作系统上。
以 Docker 为例,其就是一个基于 Linux 操作系统的 Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。
简单来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器则是把一个个应用单独封装隔离,从而实现跨平台应用。所以容器体积比虚拟机小很多,理论上占用资源更少。容器化就是应用程序级别的虚拟化技术。容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。
3、JVM 之类的虚拟机
存在于函数库层和应用程序之间的虚拟化技术。Java 虚拟机同样具有跨平台特性,所谓跨平台特性实际上也就是虚拟化的功劳。我们知道 Java 语言是调用操作系统函数库的,JVM 就是在应用层与函数库层之间建立一个抽象层,对下通过不同的版本适应不同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调用不同操作系统的函数库。
二、什么是 docker
docker 的本质
Docker 本质其实不是容器,而是容器的易用工具。容器是 linux 内核中的技术,Docker 只是把这种技术在使用上简易普及了,调用 Linux 中的容器接口。
Docker 作为容器技术的一个实现,是容器技术普及开来的最成功的实现;其是基于 Go 语言实现的一个开源项目,它的主要目标是通过对组件的封装、分发、部署、运行等生命周期的管理,使得用户的应用及其运行环境能够做到“一次封装,到处运行”。
Docker在创建容器时,是通过镜像技术(把一个操作系统用户空间所需要使用到的组件事先编排好,并整体打包成一个 image 文件),把镜像文件集中放在一个仓库中。当需要创建容器时,Docker 调用 LXC 的工具 lxc-create,连接到镜像服务器上下载匹配的镜像文件,而后基于镜像启动容器。
所以,Docker 极大的简化了容器的使用难度。以后我们创建启动容器,只需要一个命令,docker-run,docker-stop 就可以启动停止一个容器了。
docker 与虚拟机的区别
传统虚拟机 | docker 容器 | |
磁盘占用 | 几个 GB 到几十个 GB 左右 | 几十 MB 到几百 MB 左右 |
CPU 内存占用 | 虚拟操作系统非常占 CPU 和内存,需要通过虚拟层调用,占用率高 | Docker 引擎占用资源极低,直接作用于硬件资源,占用率少 |
启动速度 | (从开机到运行项目)几分钟 | (从开启容器到运行项目)几秒 |
安装管理 | 需要专门的运维技术 | 安装、管理方便 |
应用部署 | 手动部署,速度慢 | 体系化部署,可以自动化,速度快 |
隔离性 | 系统级别 | 进程级别 |
封装程度 | 打包整个操作系统 | 仅打包项目代码和依赖信息 |
重要问题:为什么 docker 比迅疾资源利用率更高,启动更快?
从上图中我们可以看到:
1、docker 有比虚拟机更少的抽象层。docker 不需要 Hypervisor 实现硬件资源虚拟化,运行在 docker 容器上的程序直接使用的是实际物理机的硬件资源。因此在 cpu、内存利用率上 docker 将会在效率上有明显的优势。
2、docker 利用的是宿主机的内核,而不需要 Guest OS,节省了 Guest OS 占用的资源。
3、docker 不需要 Guest OS,其共享操作系统内核,创建一个容器时,也就不需要和虚拟机一样重新加载一个操作系统内核,从而避免引寻、加载操作系统内核返回时耗时耗资源的过程。当新建一个虚拟机时,虚拟机软件需要加载 Guest OS,返回新建过程是分钟级别的。而新建一个 docker 容器只需要几秒钟。
三、docker 官方架构
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程 API 来管理和创建 Docker 容器。
Docker 容器则通过 Docker 镜像来创建。

Docker 仓库(图中的 Registry)
Docker 仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub 提供了庞大的镜像集合以供使用。
Docker daemon
Docker daemon 是服务器组件,是 Docker 最核心的后台进程,我们也把它称为守护进程。
Docker 客户端(图中的 Client)
Docker 客户端通过命令行或者其他工具,使用 Docker API 与 Docker 的守护进程通信。
Docker 主机(图中的 Host)
一个物理或者虚拟的机器;用于执行 Docker 守护进程和容器。
Docker 镜像(图中的 Images)
用于创建 Docker 容器的模板,相同的镜像可以初始化多个容器。
Docker 容器(图中的Container)
独立运行的一个或一组应用。
便于理解的生活案例
上面概念比较难以理解,我们以一家人去旅游入住酒店为例,便于理解:
1、我们一家人和朋友一块旅游去酒店,我们就是 Docker 客户端。
2、到酒店办理入住,办理退房,缴费都需要酒店前台提供各种服务,这个酒店前台就是我们的 Docker Daemon,即Docker 的核心服务端。
3、酒店是建在美丽的海边,酒店的宅基地和大楼就是我们实际的物理服务器或者虚拟服务器,也就是 Docker Host。
4、酒店就 1000 多个房间,不同种类房间里面不一样,有标间、大床房、家庭房等,这就是 Docker 镜像仓库。
4、酒店各个种类的房间,如豪华大床房、双人标间等,这些个就是 Docker 镜像,我们客户是没有办法修改的。
5、当我们办理完入住了一个豪华大床房,然后把行李,个人物品带到了一个具体的房间,那么这个房间我们就可以使用了;朋友也开了一间豪华大床房,虽然豪华大床房一样,但我们携带的物品,我们的洗漱时间,睡觉时间都不一样,不同的客户入住后的不同房间就是容器 Docker Container。
6、当我们一周后的旅游结束,搬出了酒店,酒店就会把我们的房间恢复成镜像原来的样子。这也就是容器的销毁。
四、番外篇:大数据时代 docker 针对各种情况的解决方案。
如今大数据时代,有许多新的诉求,针对这些诉求,我们可以基于 docker 给出一些解决方案。
1、面对海量数据,应该如何处理?
答:购买大量的服务器,并研发对应软件
2、如果开发的需求需要频繁的变更上线,如何才能将修改的代码快速的分发到几百或者几千台服务器?如何共享软件?
答:搞一个中心仓库,让各个服务器基于各自的需要,去下载对应软件包,进行安装;因此 CentOS 搞了 yum 仓库,docker 设计了镜像仓库,docker hub 就是公共的托管仓库。
3、软件设计好以后,怎么快速安装启动,有问题又该如何回滚?
答:可以将 docker 需要的所有信息设计一套软件格式,把所有的依赖搞进去,并打上版本标签,
这样就不会导致换一个服务器就出现各种问题,Docker 也就基于此设计了镜像。
4、面对不同的开发环境,应该如何搭建?比如一会 java,一会 c++?
docker 同样是通过镜像来应对,镜像里面存放了需要运行的环境,就像我们的 iPhone 内置 ios,我们的华为 mate 50 内置鸿蒙一样,一条命令就可以完成某个环境的搭建。