本篇文章对docker的一些基础概念和周边概念进行了详细解释。帮助你可以很好的理解docker是用来干什么的,docker是怎么工作的。其中有docker所运用到的技术解释,docker的不同发展版本,dokcer的架构,docker的生态等等详解。希望本片文章会对你有所帮助。
文章目录[1、1 什么是虚拟化、容器化](#1、1 什么是虚拟化、容器化)
[1、2 为什么要虚拟化、容器化?](#1、2 为什么要虚拟化、容器化?)
[2、1 虚拟化常见类别](#2、1 虚拟化常见类别)
[2、2 常见虚拟化实现](#2、2 常见虚拟化实现)
[2、2、1 主机虚拟化(虚拟机)实现](#2、2、1 主机虚拟化(虚拟机)实现)
[2、2、2 容器虚拟化实现](#2、2、2 容器虚拟化实现)
[2、2、3 容器虚拟化基础之 NameSpace](#2、2、3 容器虚拟化基础之 NameSpace)
[2、2、4 容器虚拟化基础之 cgroups。](#2、2、4 容器虚拟化基础之 cgroups。)
[2、2、5 容器虚拟化基础之 LXC](#2、2、5 容器虚拟化基础之 LXC)
[2、3 Docker 是什么](#2、3 Docker 是什么)
[2、3、1 Docker的本质](#2、3、1 Docker的本质)
[2、3、2 Docker 的引擎迭代](#2、3、2 Docker 的引擎迭代)
[2、3、3 Docker 和虚拟机的区别](#2、3、3 Docker 和虚拟机的区别)
[2、3、4 Docker 为什么比虚拟机资源利用率高,启动快](#2、3、4 Docker 为什么比虚拟机资源利用率高,启动快)
🙋♂️ 作者:@Ggggggtm 🙋♂️
👀 专栏:Docker 👀
💥 标题:docker入门概念详解 💥
❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️
一、虚拟化与容器化
1、1 什么是虚拟化、容器化
- **物理机:**实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境,有时也称为"寄主"或"宿主"。
- 虚拟化:是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。
- 容器化:容器化是一种虚拟化技术,又称操作系统层虚拟化(Operating system level virtualization),这种技术将操作系统内核虚拟化,可以允许用户空间软件实例(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运 行。这个软件实例,也被称为是一个容器(containers)。对每个实例的拥有者与用户 来说,他们使用的服务器程序,看起来就像是自己专用的。容器技术是虚拟化的一种。 docker 是现今容器技术的事实标准。
1、2 为什么要虚拟化、容器化?
虚拟化和容器化的最主要目的就是资源隔离,随着资源隔离的实现逐渐也带来了更大的收益。
- 资源利用率高:将利用率较低的服务器资源进行整合,用更少硬件资源运行更多业务,降低 IT 支出和运维管理成本。
- 环境标准化:一次构建,随处执行。实现执行环境的标准化发布,部署和运维。开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「 这段代码在我机器上没问题啊*」*这类问题。
- 资源弹性伸缩:根据业务情况,动态调整计算、存储、网络等硬件及软件资源。比如遇到双 11 了,把服务扩容 100 个,双 11 过去了, 把扩容的 100 个收回去。
- 差异化环境提供:同时提供多套差异化的执行环境,限制环境使用资源。比如我的服务一个以来 Ubuntu 操作系统,一个服务依赖 CentOS 操作系统,但是没有预算购买两个物理机,这个时候容器化就能很好的提供多种不同的环境。
- 沙箱安全:为避免不安全或不稳定软件对系统安全性、稳定性造成影响,可使用虚拟化技术构建虚拟执行环境。比如我在容器里面执行 rm -rf /* 不会把整个服务器搞死,也不影响其他人部署的程序使用。
- 容器对比虚拟机更轻量,启动更快:传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统 ,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。docker 不需要虚拟内核,所以启动可以更快,相当于 windows 的开机时间省去了。
- 维护和扩展容易:Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。比如 docker hub 提供了很多镜像,各个系统的一个命令就可以拿到了,研发也可以自己定制镜像分享给各个产品。
二、虚拟化实现方式
2、1 虚拟化常见类别
虚拟机 :存在于硬件层和操作系统层间的虚拟化技术。虚拟机通过**"伪造"**一个硬件抽象接口, 将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样 的功能。比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台 电脑打开 Android 系统上的应用。
容器 :存在于操作系统层和函数库层之间的虚拟化技术。容器通过**"伪造"**操作系统的接口, 将函数库层以上的功能置于操作系统上。以 Docker 为例,其就是一个基于 Linux 操作系统的 Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。简单来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器则是把一个个应用单独封装隔离,从而实现跨平台应用。所以容器体积比虚拟机小很多,理论上占用资源更少。容器化就是应用程序级别的虚拟化技术。容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。
JVM 之类的虚拟机: 存在于函数库层和应用程序 之间的虚拟化技术。 Java 虚拟机同样具有跨平台特性,所谓跨平台特性实际上也就是虚拟化的功劳。我们知道 Java 语言是调用操作系统函数库的,JVM 就是在应用层与函数库层之间建立一个抽象层,对下通过不同的版本适应不同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调用不同操作系统的函数库。
2、2 常见虚拟化实现
2、2、1主机虚拟化(虚拟机)实现
主机虚拟化的原理是通过在物理服务器上安装一个虚拟化层来实现。这个虚拟化层可以在物理服务器和客户操作系统之间建立虚拟机,使得它们可以独立运行。
从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之上,将虚拟化划分为 Type1 和 Type2。
Type1 类的 Hypervisor(Hypervisor 是一种系统软件,它充当计算机硬件和虚拟机之间的中介,负责有效地分配和利用由各个虚拟机使用的硬件资源,这些虚拟机在物理主机上单独工作,因此,Hypervisor 也称为虚拟机管理器。 ) 直接运行在硬件之上,没有宿主机操作系统,Hypervisor 直接控制硬件资源和客户机。典型框架为 Xen 、 VmwareESX。
Type2 类的 Hypervisor 运行在一个宿主机操作系统之上(Vmware Workstation)或者系统里面,Hypervisor 作为宿主机操作系统中的一个应用程序,客户机就是在宿主机操作系统上的一个进程。
2、2、2 容器虚拟化实现
容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。通过 namespace 进行各程
序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。
2、2、3 容器虚拟化基础之 NameSpace
**什么是****Namespace(**命名空间)呢? namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。
Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前namespace 里的进程,对其他 namespace 中的进程没有影响。
Linux 提供了多个 API 用来操作 namespace,它们是 clone()、setns() 和 unshare() 函数,为了确定隔离的到底是哪项 namespace,在使用这些 API 时,通常需要指定一些调用参数:CLONE_NEWIPC、CLONE_NEWNET、CLONE_NEWNS、CLONE_NEWPID、CLONE_NEWUSER、CLONE_NEWUTS 和 CLONE_NEWCGROUP。如果要同时隔离多个 namespace,可以使用 | (按位或)组合这些参数。
以上命名空间在容器环境下的隔离效果:
- UTS:每个容器能看到自己的 hostname,拥有独立的主机名和域名。
- IPC:同一个 IPC namespace 的进程之间能互相通讯,不同的 IPC namespace 之间不能通信。
- PID:每个 PID namespace 中的进程可以有其独立的 PID,每个容器可以有其 PID 为 1 的 root 进程。
- Network:每个容器用有其独立的网络设备,IP 地址,IP 路由表,/proc/net 目录,端口号。
- Mount:每个容器能看到不同的文件系统层次结构。
- User:每个 container 可以有不同的 user 和 group id。
2、2、4 容器虚拟化基础之 cgroups**。**
什么是cgroups?**cgroups(Control Groups) 是 linux 内核提供的一种机制,**这种机制可以根据需求把一系列系统任务及其子任务整合**(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。**简单说,cgroups 可以限制、记录任务组所使用的物理资 源。本质上来说,cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。
**为什么使用 cgroups?**其可以做到对 cpu,内存等资源实现精细化的控制,目前越来越火的轻量级容器Docker 及 k8s 中的 pod 就使用了 cgroups 提供的资源限制能力来完成 cpu,内存等部分的资源控制。比如在一个既部署了前端 web 服务,也部署了后端计算模块的八核服务器上,可以使用 cgroups 限制 web server 仅可以使用其中的六个核,把剩下的两个核留给后端计算模块。
cgroups 的用途?
- Resource limitation: 限制资源使用,例:内存使用上限/cpu 的使用限制。
- Prioritization: 优先级控制,例:CPU 利用/磁盘 IO 吞吐。
- Accounting: 一些审计或一些统计。
- Control: 挂起进程/恢复执行进程。
cgroups****可以控制的子系统。
2、2、5 容器虚拟化基础之 LXC
LXC 是什么?LXC(LinuX Containers)Linux 容器,一种操作系统层虚拟化技术,为 Linux 内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container**),内含应用软件本身的代码,以及所需要的操作系统核心和库**。透过统一的名字空间和共享 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。
LXC 是最早一批真正把完整的容器技术用一组简易使用的工具和模板来极大的简化了容器技术使用的一个方案.
LXC 虽然极大的简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会 LXC 的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。其隔离性也没有虚拟机那么强大。后来就出现了 docker ,所以从一定程度上来说, docker 就是 LXC 的增强版。
2、3 Docker 是什么
2、3、1 Docker的本质
Docker 本质其实是 LXC 之类的增强版,它本身不是容器,而是容器的易用工具。容器是 linux 内核中的技术,Docker 只是把这种技术在使用上简易普及了。Docker 在早期的版本其核心就是 LXC 的二次封装发行版。
Docker 作为容器技术的一个实现,或者说让容器技术普及开来的 最成功 的实现。Docker 是基于 Go 语言实现的一个开源项目,它的主要目标是 "Build , Ship and Run Any APP, Anywhere" ,即通过对组件的封装、分发、部署、运行等生命周期的管理,使得用户的应用及其运行环境能够做到**"** 一次封装,到处运行 " 。
早期 Docker 利用 LXC 做容器管理引擎,但是在创建容器时,不再使用模板去安装生成,而是通过镜像技术(把一个操作系统用户空间所需要使用到的组件事先编排好,并整体打包成一个文件,image 文件),镜像文件集中放在一个仓库中。当需要创建容器时,Docker 调用 LXC 的工具 lxc-create ,但不再通过 lxc 的模板去安装,而是连接到镜像服务器上下载匹配的镜像文件,而后基于镜像启动容器。所以,Docker 极大的简化了容器的使用难度。以后我们创建启动容器,只需要一个命令,docker-run ,docker-stop 就可以启动停止一个容器了。
2、3、2 Docker 的引擎迭代
Docker 早期是基于 LXC 容器管理引擎实现,当后来成熟之后,Docker 自建了一个容器引擎叫 libcontainer,后来 CNCF 的介入,Docker 又研发了一个工业化标准的容器引擎 runC,目前所使用的新版 Docker,所使用的容器引擎就是 RunC。
2、3、3 Docker 和虚拟机的区别
虚拟机(Virtual Machine,VM)是一种完整的操作系统(OS)实例,可以在物理计算机上运行。每个虚拟机都包含自己的操作系统、应用程序和系统资源,例如内存、处理器等。虚拟机通过虚拟化层与底层物理硬件进行通信,提供了强大隔离性和安全性。每个虚拟机都需要额外的资源和运行时间来启动和运行。
Docker是一种轻量级的容器化技术,它利用操作系统级别的虚拟化(OS-level virtualization),将应用程序及其所有依赖项封装在一个可移植的容器中。Docker容器与主机共享操作系统内核,因此相对于虚拟机而言,更加轻量级和高效。Docker容器可以更快地启动、停止和迁移,并且更节省资源。
他们之间的主要对比如下图:
2、3、4 Docker 为什么比虚拟机资源利用率高,启动快
docker 有比虚拟机更少的抽象层。docker 不需要 Hypervisor 实现硬件资源虚拟化,运行在 docker 容器上的程序直接使用的是实际物理机的硬件资源。因此在 cpu、内存利用率上 docker 将会在效率上有明显的优势。docker 利用的是宿主机的内核,而不需要Guest OS,节省了 Guest OS 占用的资源。
docker 不需要 Guest OS ,创建一个容器时,不需要和虚拟机一样重新加载一个操作系统内核。从而避免引寻、加载操作系统内核返回时耗时耗资源的过程,当新建一个虚拟机时,虚拟机软件需要加载 Guest OS, 返回新建过程是分钟级别的。而新建一个docker 容器只需要几秒钟。
三、docker的版本
- lxc:上文中提到,lxc 是最早的 linux 容器技术,早期版本的 docker 直接使用 lxc 来实现容器的底层功能。虽然使用者相对较少,但 lxc 项目仍在持续开发演进中。
- libcontainer:docker 从 0.9 版本开始自行开发了 libcontainer 模块来作为 lxc 的替代品实现容器底层特性,并在 1.10 版本彻底去除了 lxc。在 1.11 版本拆分出 runc 后,libcontainer 也随之成为了 runc 的核心功能模块,runc 后续变成了容器标准。
- moby:moby 是 docker 公司发起的开源项目,其中最主要的部分就是同名组件 moby,事实上这个 moby 就是 dockerd目前使用的开源项目名称,docker 项目中的 engine (dockerd)仓库现在就是从 moby 仓库 fork 而来的,使用 containerd 作为运行时标准。https://mobyproject.org/
- docker-ce:docker 的开源版本,CE 指 Community Edition。docker-ce 中的组件来自于moby、containerd 等其他项目。https://www.docker.com/pricing/
- docker-ee:docker 的收费版本,EE 指 Enterprise Edition。其基础组件来源和 docker-ce 是 一样的,但附加了一些其他的组件和功能。
Docker 发展过程中衍生了以上版本,目前我们学习和使用提到的版本是 docker-ce 。
四、docker架构
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程 API 来管理和创建 Docker 容器。Docker 容器通过 Docker 镜像来创建的。Docker官方架构如下:
Docker 官方架构包括以下几个核心组件:
Docker Client(Docker 客户端):客户端是与 Docker Daemon 交互的命令行工具或图形界面工具。用户可以使用客户端来向 Docker 守护进程发送请求,以执行容器的创建、启动、停止等操作。
Docker Host(Docker 主机):一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker Daemon(Docker 守护进程):守护进程是 Docker 的后台服务,负责管理和运行容器。它接受 Docker API 请求,并执行相关操作,如创建、启动、停止、删除容器等。Docker Daemon 运行在主机上,并通过 RESTful API 与客户端进行通信。
Docker 镜像(Docker Images):镜像是用于创建 Docker 容器的模板。它包含了应用程序运行所需的所有文件系统、库和依赖项。镜像是只读的,可以通过 Docker Hub 或私有仓库获取。用户可以基于现有镜像创建自定义镜像,也可以将自定义镜像推送到仓库供其他用户使用。
Docker 容器(Docker Containers):容器是基于镜像创建的运行实例。容器是基于镜像创建的可运行实例。每个容器都是一个隔离的环境,包含了应用程序和其依赖项。容器具有自己的文件系统、网络和进程空间,可以独立地运行在宿主机上。容器可以被启动、停止、删除和迁移,使得应用程序的部署和管理变得更加灵活和高效。
Docker Registry(Docker 仓库):仓库是用于存储和分发 Docker 镜像的集中位置。Docker Hub 是 Docker 官方提供的公共仓库,用户可以在其中找到大量的官方和社区维护的镜像。此外,用户还可以搭建私有仓库来存储自己的镜像。
五、docker的生态
我们来考虑 2 个问题,Docker 为什么要设计镜像,然后又搭建个 Docker Hub,搞个镜像仓库呢?我们来看下现在的时代发生了什么。
- **数据量疯狂增长:**随着物联网、边缘计算等智能终端设备不断普及,受到来自物联网设备信号、元数据、娱乐相关数据、云计算和边缘计算的数据增长的驱动,全球数据量呈现加速增长。根据 IDC 分布的《数据时代 2025》预测,全球数据量将从 2018 年的 33ZB 增至 2025年的 175ZB,增长超过 5 倍;中国平均增速快于全球 3%,预计到 2025 年将增至48.6ZB,占全球数据圈的比例由 23.4%提升至 27.8%。其中,中国企业级数据量将从2015 年占中国数据量的 49%增长到 2025 年的 69%。
- **处理能力快速增加:**腾讯云全球服务器数量 100w+,数据量 EB+;2020 年阿里云:在全国已建成 5 大超级数据中心,阿里云在全球 22 个地域部署了上百个数据中心,服务器的总规模数已经接近 200 万台。某省疾控中心疫苗预约系统、全员核酸检测系统、健康码系统共 300 余台服务器,并为核酸检测系统快速扩容计算和存储资源。
- 软件需求爆发式增长:
- 软件发布频繁:研发模式从瀑布开发演变为敏捷开发,原来 3 个月上一次新功能,现在两周一次,而开发过程中我们也经常遇到需要修改需求,然后变更再发布的情况。软件上线有问题需要快速回滚,对软件有着极强的版本管理和回滚诉求。
- 软件需要共享:软件的研发人员、研发公司在设计、研发好一款软件的时候,如何方便的共享给他人,而又能快速的使用起来。
- 环境搭建复杂,技术种类繁多:每个项目组使用的语言不一样,需要不同的环境,每个都得搞一套。每次都要从 yum开始一个个完成部署安装,每次都有各种奇怪的问题,运维成本很高。
接下来我们看一下 docker 的解决方法。云时代需要我们针对这些诉求有一套针对的解决方案。
- 我们要处理海量的数据,如何处理呢?购买大量的服务器,并研发对应软件。
- 开发的需求需要频繁的变更上线,如何才能将修改的代码快速的分发到几百或者几千台服务器呢?如何共享软件呢?搞一个中心仓库,让各个服务器去下载软件包,安装。所以 CentOS 搞了 yum 仓库,docker 设计了镜像仓库, docker hub 是公共的托管仓库。
- 软件设计好以后,怎么快速安装启动,有问题回滚呢?将 docker 需要的所有信息设计一套软件格式,把所有的依赖搞进去,并打上版本标签,这样不会换一个服务器各种问题,所以 Docker 设计了镜像。
- 不同的开发环境怎么搭建呢,一会 java,一会 c++?docker 设计了镜像来应对,镜像里面存放了需要运行的环境,就像我们的 iPhone 内置 ios,我们的华为 mate 50 内置鸿蒙一样,一条命令就可以完成某个环境的搭建。