记得之前曾经粗略的写过一篇Docker的基础及ASP.NET Core部署Docker示例的入门文章,但那个时候刚刚学习Docker对Docker的认知还比较浅,现在重新来温故知新一下。此外,本篇已加入《.NET Core on K8S学习实践系列文章索引》,可以点击查看更多容器化技术相关系列文章。

一、容器的用途

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

1、标准化打包

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

2、隔离

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

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

3、标准化部署

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

二、容器与集装箱的关系

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

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

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

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

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

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

三、容器核心技术揭秘

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的就实现了基础镜像层的复用。

四、容器的架构一览

  有了之前的基础知识,最后我们再来看看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/

五、关于Docker Compose

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

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

$docker-compose up

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

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

六、小结

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

参考资料

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

EdisonZhou,《ASP.NET Core on Docker入门

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

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

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

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

温故知新:Docker基础知识知多少的更多相关文章

  1. Docker基础入门

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  2. Docker基础与实战,看这一篇就够了

    docker 基础 什么是Docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Uni ...

  3. Docker - Docker基础命令及使用

    Docker Docker - 官网 Docker - Hub GitHub - Docker Docker中文社区 Docker基础命令 Docker 查看帮助信息:docker --help 查看 ...

  4. 【云计算】Docker云平台—Docker基础

    Docker云平台系列共三讲,此为第一讲:Docker基础 参考资料: Docker官方文档:https://docs.docker.com/ Docker从入门到实践:https://yeasy.g ...

  5. Docker基础技术:Linux Namespace(下)

    在 Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中,主 ...

  6. Docker 基础技术:Linux Namespace(下)

    导读 在Docker基础技术:Linux Namespace(上篇)中我们了解了,UTD.IPC.PID.Mount 四个namespace,我们模仿Docker做了一个相当相当山寨的镜像.在这一篇中 ...

  7. Docker基础入门及示例

    Docker近几年的发展可谓一日千里,特别从是2013年随着一个基于LXC的高级容器引擎开源,到现在,其在linux和windows上都有了很好的支持,并且已经有很多公司将docker用于实际的生产环 ...

  8. Docker 基础 : 镜像

    目录 获取镜像 查看镜像信息 搜索镜像 删除镜像 创建镜像 导出和导入镜像 上传镜像 总结 镜像是 Docker 的三大核心概念之一.Docker 运行容器前需要本地存在对应的镜像,如果本地没有对应的 ...

  9. Docker 基础技术之 Linux cgroups 详解

    PS:欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 推荐大家到公众号阅读,那里阅读体验更好,也沉淀了很多篇干货. 前面两篇 ...

  10. docker 基础知识分享ppt

    给团队做的docker基础分享ppt, 见下面的附件. https://files.cnblogs.com/files/harrychinese/docker_intro.pptx

随机推荐

  1. Visual Studio 2017 导出 ASP.NET Core 项目模版项目文件为空

    问题重现 VS 2017 针对 ASP.NET Core 导出模版功能有问题 解决办法 visual-studio-2017-templates-and-the-missing-content 目前官 ...

  2. Browser-use:基于 Python 的智能浏览器自动化 AI 工具调研与实战

    Browser-use:基于 Python 的智能浏览器自动化 AI 工具调研与实战 一.概述 Browser-use 是一个旨在将 AI "智能体"(Agents)与真实浏览器进 ...

  3. 记一次 .NET某云HIS系统 CPU爆高分析

    一:背景 1. 讲故事 年前有位朋友找到我,说他们的系统会偶发性的CPU爆高,有时候是爆高几十秒,有时候高达一分多钟,自己有一点分析基础,但还是没找到原因,让我帮忙看下怎么回事? 二:CPU爆高分析 ...

  4. 使用Python对理想气体进行建模

    引言 在日常生活中,我们常常听到"气体",但你是否知道气体的行为是如何被科学家们用数学模型描述的呢?今天,我们就来聊聊如何用 Python 对理想气体进行建模,帮助大家更好地理解气 ...

  5. Spring框架中的单例bean是线程安全的吗?

    1.介绍两个概念 有状态的bean:对象中有实例变量(成员变量),可以保存数据,是非线程安全的 无状态的bean:对象中没有实例变量(成员变量),不能保存数据,可以在多线程环境下共享,是线程安全的 2 ...

  6. addAll(Collection<? extends E> c)的方法源码

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  7. 什么是 Java 中的常量池?

    Java 中的常量池 Java 中的常量池(Constant Pool)是用于存放程序中常量(如字符串.数字.类.方法等)的内存区域.常量池的主要作用是提高内存的使用效率和性能,避免重复创建相同的常量 ...

  8. C# 拓展方法( 一)

    总结:用处在不破坏原有类封装的情况下给它添加新的方法,这样可以不需要修改这个类的源代码,也不需要再另外的继承一个类添加方法. C#中的扩展方法及用途 - 森大科技 - 博客园 (cnblogs.com ...

  9. 使用sealos快速搭建kubernetes集群!!!

    什么是sealos? Sealos 是一款基于 Kubernetes 的轻量级操作系统,专为云原生环境设计,主要用于快速部署和管理 Kubernetes 集群.它采用"容器化内核" ...

  10. 使用DVC管理大文件变更历史(基于git)

    DVC(Data Version Control) 是一个专门用于管理数据和二进制文件版本控制 的工具,它特别适合那些需要处理大量非文本文件(如图像.视频.模型.数据集等)的项目. 一般地,如果项目中 ...