温故知新:Docker基础知识知多少?

【云原生作者/Edison Zhou

这是恰童鞋骚年的第233篇原创文章


记得之前曾经粗略的写过一篇Docker的基础及ASP.NET Core部署Docker示例的入门文章,但那个时候刚刚学习对Docker的认知还比较浅,现在重新来温故知新一下。本文预计阅读时间为10min

1容器的用途

首先,我们来温习一下Docker的几个用途,亦或者说Docker到底帮我们解决什么问题

1、标准化打包

记得在容器技术出来之前,我们开发者进行打包一般都依赖于各自开发语言平台独有的打包机制,比如.NET和Java平台下都会依赖于各自不同的发布部署技术,但在容器技术出来之后,不管是.NET还是Java都会将其发布为容器镜像推送到镜像仓库中作来进行部署

2、隔离

每个容器在运行时都会认为自己是独自占有了一台机器,即一个独立的环境互不干扰。其实,容器的本质是一个进程,进程与进程之间相互隔离造就了容器与容器互不影响的特性。在启动一个容器(即创建一个进程时),通过 Namespace 技术实现容器的隔离、通过 Cgroups 来实现容器的资源控制。

关于Namespace 和 Cgroups 可以继续浏览本文3.3小节。

3、标准化部署

在容器技术出来之前,和打包机制一样,我们都依赖于具体开发语言平台的部署机制,比如IIS、Tomcat等。但是,容器技术出来之后,即使我们使用不同的开发语言都可以使用同样的部署技术,例如Mesos或Kubernetes。至此,之前的运维人员也不在需要学习多套部署技术,只需要了解如K8s一类的标准化容器编排平台即可。

2与集装箱的关联

提到容器要解决的问题,就不得不提一下运输业以及集装箱。几十年前,运输业面临着因货物类型不同而导致损失,又或者在运输过程中使用不同的交通工具也会让整个过程痛苦不堪。幸运的是,集装箱的发明帮助运输业解决了这个问题:

(1)任何货物,无论是钢琴还是玛莎拉蒂,都被放到各自的集装箱中。

(2)集装箱在整个运输过程中都是密封的,只有到达最终目的地才被打开。

(3)集装箱可以被高效地装卸、重叠和长途运输。例如:现代化的起重机可以自动在卡车、轮船和火车之间移动集装箱。

容器的核心思想其实也就是将集装箱的思想应用到了软件的打包和部署上,为各类不同的代码提供了一个基于容器的标准化运输系统。换句话说,容器可以将任何应用及其依赖环境打包为一个轻量级、可移植、自包含的独立运行环境,容器可以运行在几乎所有的操作系统之上。

不得不说,Docker的Logo就是一堆集装箱放在海豚上,作为海豚的docker就是一个标准化的运输系统

3容器实现的核心技术

1、操作系统内核(Linux)

为了进一步理解Docker,我们先来看看Linux操作系统及其内核,如下图所示:

从上图可知,最底层为硬件层,包含了内存、磁盘、CPU、网卡等;往上一层是内核空间,Kernel就是操作系统内核,负责管理硬件层中的各种资源 以及 调度进程 等工作;顶层是用户空间,用户程序就在此空间内运行,并调用内核空间提供的服务;

2、虚拟机和容器的差异

大概了解了操作系统的内核之后,我们再来看看老生常谈的容器和虚拟机的差异,如下图所示:

虚拟机:主要是由硬件虚拟化+内核虚拟化技术来实现,它在宿主机操作系统或硬件层的基础之上引入一层Hypervisor来虚拟出磁盘、CPU等资源,然后在虚拟出来的资源的基础之上运行Guest OS进而实现最终的虚拟机。

容器:直接在宿主机操作系统之上构建一个Docker Engine,共享宿主机操作系统内核,在此基础之上只引入了少量的Guest OS来实现。

对比一下:

(1)虚拟机的隔离性比容器好,因为虚拟机是一种强隔离机制;

(2)虚拟机比较重量级,启动时速度比较慢,消耗资源也比较多;

(3)容器的隔离性不如虚拟机,它是一种软件隔离机制,但它比较轻量级,引入的东西较少,所以速度快消耗资源少;因此,在同一个物理机上能够启动的容器的数量远远多于虚拟机的数量;

3、容器的核心技术

了解了操作系统的内核以及和虚拟机的差异,现在我们可以正式了解一下基于Linux内核的Docker容器核心技术到底有哪些(当然,本文只是粗略的介绍一下,更详细的部分请浏览本文的参考资料文章),如下图所示:

(1)CGroups:

容器进程创建好后,若不进行其他处理,该进程运行时所消耗及占用的资源(如 CPU、内存)等,是可以被其他宿主机进程或其他容器进程享用的。为了解决这个问题,Linux 容器设计中引入了 Cgroups 的概念。

Linux CGroups 的全称是 Linux Control Group,它的主要作用就是限制一个进程(这里也可以指容器)能够使用的资源上限(如 Cpu、内存、网络等等)。关于Docker的资源限制,可以阅读我这一篇《Docker资源限制学习与验证》文章。

(2)Namespaces:

刚刚提到,容器的本质是一个进程,进程与进程之间相互隔离造就了容器与容器互不影响的特性。在启动一个容器(即创建一个进程时),通过 Namespaces 技术实现容器的隔离。

容器进程的创建通过 Linux 平台下的 Clone 方法创建,在调用该方法创建进程时,通过指定额外的 Namespace 参数,使得刚创建的进程属于一个独立的空间。

int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL)
指定额外参数 CLONE_NEWPID 创建的新进程,有一个自己的 独立进程空间,在这个空间里,它的进程 ID 为 1。它既看不到其在宿主机的真正进程、也看不到其他容器的进程。

(3)Networking

容器的创建还需要网络的支持,Networking这一块主要是虚拟网卡、网桥及iptables为容器提供组网支持;

(4)Storage

最后,容器的创建还需要存储的支持,Storage这一块提供了容器支持的一些文件系统,如Device Mapper、Btrfs 及 Aufs 等等;

4、容器的镜像

刚刚提到,容器镜像为标准化打包提供了基础。容器镜像采用的是分层的方式来组织的,如下图所示:

可以看到,底层的是基础镜像,称为Base Image,例如Ubuntu、CentOS等,它可以和宿主机的OS是不一样的,但是它会共享宿主机操作系统的内核;在基础镜像之上,可以有多层镜像,例如Java JDK的依赖,.NET Core Runtime依赖等;依赖层之上呢,可以是具体的应用程序的Release。

综上所述,容器镜像采用分层的方式进行组织,可以很方便地实现镜像层的复用。如果两个容器所依赖的底层镜像层是相同的,可以共同应用同一个Hash值的底层镜像,进而也可以节省传输和网络的开销。例如,图中Image1和Image2的就实现了基础镜像层的复用。

4容器的架构一览

有了之前的基础知识,最后我们再来看看Docker的架构,如下图所示:

从上图可以看出,一个典型的Docker架构包含了三块内容:

(1)Docker Registry:镜像仓库,主要负责存储镜像,官方的仓库是Docker Hub,你也可以基于开源项目Harbor或者使用阿里云等云服务厂商提供的镜像仓库服务来搭建私有镜像仓库,如果有兴趣可以参考我的这一篇《Docker常用流行镜像仓库搭建》。

(2)Docker Host:Docker宿主,首先它会运行一个Docker daemon,会接收Docker Client发送的指令来执行拉取镜像、缓存、启动等操作;其次,Docker daemon执行完Docker Client发送过来的指令后,所有的容器都会在Docker Host上运行;

(3)Docker Client:客户端操作,主要负责通过docker命令行对容器进行基本操作,如拉取镜像,构建镜像,运行容器等等;

更多关于Docker架构的内容请参考(也可以直接点击本文底部“阅读原文”):https://docs.docker.com/get-started/overview/

5关于Docker Compose

Docker主要用来运行单容器应用,而Docker Compose则是一个用来定义和应用多容器应用的工具,如下图所示:

使用Docker Compose,我们可以将多容器的定义和部署方式定义在一个yml文件中,这种方式特别是微服务这种架构风格,可以将多个微服务的定义及部署都规范在一个yml文件中,然后一键部署、启动或销毁整个微服务应用。所有的一切操作,只需要下面的一句话:

$docker-compose up
很多人建议在本地测试环境,使用Docker Compose来快速的部署和测试微服务应用,在生产环境则建议使用Kubernetes这种生产级的容器云平台。

如果对Docker Compose感兴趣,我之前也有写一篇使用Docker Compose来编排Spring Cloud微服务的示例文章,有兴趣可以看看。

6小结

本文从Docker容器要解决的几个问题入手,介绍了容器与集装箱的关联、容器的核心实现技术、容器的架构,最后简单介绍了一个Docker Compose这个多容器应用工具,相信能够从背景知识上帮你了解容器到底要帮助我们解决的问题。

7参考资料

杨波,《Spring Boot与Kubernetes云原生应用实践》(强力推荐订阅学习)

EdisonZhou,《ASP.NET Core on Docker入门》

EdisonZhou,《Docker资源限制学习与验证》

godruoyi,《容器的工作原理和隔离机制》

CloudMan,《每天5分钟玩转Docker容器技术》

往期精彩回顾

.NET Core on K8s学习系列文章目录

基于Jenkins的开发测试全流程持续集成实践

基于Jenkins的ASP.NET Core持续集成实践

如果本文对你有用,

不妨点个“在看”/转发朋友圈

????点击了解Docker更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[C++11]lambda表达式语法

代码如下: #include <iostream> using namespace std;void func(int x, int y) {int a;int b;[]() {int c a;//使用了外部变量&#xff0c;[]里面加个 int d x;}; }int main() {return 0; }lambda表达式的注意事项: 以上图片来自下面链接: https://subingwen.cn/cpp…

[翻译]欢迎使用C#9.0

本文由公众号[开发者精选资讯](微信号&#xff1a;yuantoutiao)翻译首发&#xff0c;转载请注明来源C# 9.0 is taking shape, and I’d like to share our thinking on some of the major features we’re adding to this next version of the language.C&#xff03;9.0初具规…

操作系统第四章习题

操作系统第四章习题 1.对一个将页表放在内存中的分页系统&#xff1a; (1) 如果访问内存需要0.2μs&#xff0c;有效访问时间为多少? (2) 如果加一快表&#xff0c;且假定在快表中找到页表的几率高达90%&#xff0c;则有效访问时间又是多少&#xff08;假定查快表需花的时间…

[C++11]右值和右值引用

代码如下: #include <iostream> using namespace std;int main() {//左值int num 9;//左值引用int &a num;//右值const int N 5;//右值引用int && b 8;//常量左值引用const int &c num;//常量右值引用const int &&d 6;//const int &&…

我们为什么推荐在Json中使用string表示Number属性值

在这篇简短的文章中&#xff0c;我将解释在使用JSON传输数据时&#xff0c;为什么浮点数或大十进制值应表示为字符串 。long类型引发的诡异情况长话短说&#xff0c;同事在利用swagger对接后端API时&#xff0c;诡异的发现swaggerUI中显示的json属性值并不是api返回的值。[Http…

并查集+基础知识点详解

并查集概念 并查集单看名字大家也能猜到这个算法的作用&#xff0c;是用来对集合进行合并和查找操作 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。——来自百度百科 就是将原本不一样的集合&#xff0c;但是由于某种关系有…

[C++11]move资源的转移

从实现上讲&#xff0c;std::move 基本等同于一个类型转换&#xff1a;static_cast<T&&>(lvalue);&#xff0c;函数原型如下: template<class _Ty> _NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) _NOEXCEPT { …

基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型

上一篇文章使用自定义仓储完成了简单的增删改查案例&#xff0c;有心的同学可以看出&#xff0c;我们的返回参数一塌糊涂&#xff0c;显得很不友好。在实际开发过程中&#xff0c;每个公司可能不尽相同&#xff0c;但都大同小异&#xff0c;我们的返回数据都是包裹在一个公共的…

奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革&#xff1a;重新分配房子。 这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住&#xff08;如果有老百姓没房子住的话&#xff0c;容易引起不安定因素&…

记一次排查线上程序内存的忽高忽低,又是大集合惹祸了

一&#xff1a;背景1. 讲故事昨天继续还技术债&#xff0c;优化一轮后的程序拉到线上后内存继续忽高忽低&#xff0c;低的时候20G&#xff0c;高的时候30G&#xff0c;过了一会又下降了几个G&#xff0c;毫无疑问&#xff0c;程序中有什么集合或者什么操作占用了大量内存&#…

[C++11]forward完美转发

// 函数原型 template <class T> T&& forward (typename remove_reference<T>::type& t) noexcept; template <class T> T&& forward (typename remove_reference<T>::type&& t) noexcept;// 精简之后的样子 std::forward…

Pipe HDU - 2150(判断线段相交+向量叉乘线代详解)

题目&#xff1a; 经过激烈的争夺&#xff0c;Lele终于把那块地从Yueyue的手里抢了回来。接下来&#xff0c;Lele要开始建造他的灌溉系统。 通过咨询Lele的好友——化学系的TT&#xff0c;Lele决定在田里挖出N条沟渠&#xff0c;每条沟渠输送一种肥料。 每条沟渠可以看作是一…

win7如何将计算机移至桌面,如何将win7电脑桌面的文件转移到其他盘中?

想必很多朋友都和小编一样&#xff0c;是一个嫌麻烦的人&#xff0c;是一个不怎么爱收拾的人吧?这种人有一个通病&#xff0c;那就是喜欢将一些重要的文件放置在win7 64位纯净版下载的桌面上&#xff0c;这样的话&#xff0c;不仅容易找到&#xff0c;而且方便使用&#xff0c…

凸包算法知识总结

首先&#xff0c;什么是凸包&#xff1f; 假设平面上有p0~p12共13个点&#xff0c;过某些点作一个多边形&#xff0c;使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候&#xff0c;我们就叫它“凸包”。 处理何种问题&#xff1a;凸包可以看成在木板上钉许多…

[C++11]shared_ptr使用的注意事项(内存被重复析构,内存泄漏问题)

shared_ptr使用的注意事项: 1.不能使用一个原始地址初始化多个共享智能指针 2.函数不能返回管理了this的共享智能指针对象 3.共享智能指针不能循环引用 不能使用一个原始地址初始化多个共享智能指针 代码如下: #include <iostream> #include <memory> using name…

一文解读使用WinDbg排查iis 中CPU占用高的站点问题

一、概述在Window服务器部署程序后&#xff0c;可能因为代码的不合理或者其他各种各样的问题&#xff0c;会导致CPU暴增&#xff0c;甚至达到100%等情况&#xff0c;严重危及到服务器的稳定以及系统稳定&#xff0c;但是一般来说对于已发布的程序&#xff0c;没法即时看到出问题…

Power Network POJ - 1459(EK算法模板+详解)

题意&#xff1a; 总共有a个节点&#xff0c;其中有发电站b个、用户c个和调度器a-b-c个三种节点&#xff0c;每个发电站有一个最大发电量&#xff0c;每个用户有个最大接受电量&#xff0c;现在有d条有向边&#xff0c;边有一个最大的流量代表&#xff0c;最多可以流出这么多电…

[C++11]shared_ptr共享智能指针的初始化与使用

使用智能指针需要添加头文件: 代码如下: #include <memory>shared_ptr使用的注意事项: 1.不能使用一个原始地址初始化多个共享智能指针 2.函数不能返回管理了this的共享智能指针对象 3.共享智能指针不能循环引用 初始化: 1.通过构造函数初始化 代码如下: std::shar…

人在职场,表达似水

最近几天集中在和部门内的小伙伴做1&#xff1a;1Talk。发现有不少人表达能力真的不是很好&#xff0c;而且水平长期停滞不前。现场与他们分享了一些我的经验&#xff0c;趁热打铁也想在这里分享给大家。表达能力不好本身就是做技术的人身上的一个常见标签。如果仅仅是标签也就…